00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00037 #include "vcalformat.h"
00038 #include "calendar.h"
00039 #include "event.h"
00040 #include "exceptions.h"
00041 #include "icaltimezones.h"
00042 #include "todo.h"
00043 #include "versit/vcc.h"
00044 #include "versit/vobject.h"
00045
00046 #include <KDebug>
00047
00048 #include <QtCore/QBitArray>
00049 #include <QtCore/QFile>
00050 #include <QtGui/QTextDocument>
00051
00052 using namespace KCalCore;
00053
00058
00059 template <typename K>
00060 void removeAllVCal( QVector< QSharedPointer<K> > &c, const QSharedPointer<K> &x )
00061 {
00062 Q_ASSERT( c.count( x ) == 1 );
00063 c.remove( c.indexOf( x ) );
00064 }
00065
00066 class KCalCore::VCalFormat::Private
00067 {
00068 public:
00069 Calendar::Ptr mCalendar;
00070 Event::List mEventsRelate;
00071 Todo::List mTodosRelate;
00072 QSet<QByteArray> mManuallyWrittenExtensionFields;
00073 };
00074
00075
00076 VCalFormat::VCalFormat() : d( new KCalCore::VCalFormat::Private )
00077 {
00078 #if defined(KCALCORE_FOR_SYMBIAN)
00079 d->mManuallyWrittenExtensionFields << VCRecurrenceIdProp;
00080 d->mManuallyWrittenExtensionFields << EPOCAgendaEntryTypeProp;
00081 #endif
00082 d->mManuallyWrittenExtensionFields << KPilotIdProp;
00083 d->mManuallyWrittenExtensionFields << KPilotStatusProp;
00084 }
00085
00086 VCalFormat::~VCalFormat()
00087 {
00088 delete d;
00089 }
00090
00091 bool VCalFormat::load( const Calendar::Ptr &calendar, const QString &fileName )
00092 {
00093 d->mCalendar = calendar;
00094
00095 clearException();
00096
00097 VObject *vcal = 0;
00098
00099
00100
00101 vcal = Parse_MIME_FromFileName( const_cast<char *>( QFile::encodeName( fileName ).data() ) );
00102
00103 if ( !vcal ) {
00104 setException( new Exception( Exception::CalVersionUnknown ) );
00105 return false;
00106 }
00107
00108
00109
00110
00111 QString savedTimeZoneId = d->mCalendar->timeZoneId();
00112 populate( vcal, false, fileName );
00113 d->mCalendar->setTimeZoneId(savedTimeZoneId);
00114
00115
00116 cleanVObjects( vcal );
00117 cleanStrTbl();
00118
00119 return true;
00120 }
00121
00122 bool VCalFormat::save( const Calendar::Ptr &calendar, const QString &fileName )
00123 {
00124 d->mCalendar = calendar;
00125
00126 ICalTimeZones *tzlist = d->mCalendar->timeZones();
00127
00128 QString tmpStr;
00129 VObject *vcal, *vo;
00130
00131 vcal = newVObject( VCCalProp );
00132
00133
00134 addPropValue( vcal, VCProdIdProp, productId().toLatin1() );
00135 addPropValue( vcal, VCVersionProp, _VCAL_VERSION );
00136
00137
00138 Todo::List todoList = d->mCalendar->rawTodos();
00139 Todo::List::ConstIterator it;
00140 for ( it = todoList.constBegin(); it != todoList.constEnd(); ++it ) {
00141 if ( (*it)->dtStart().timeZone().name().mid( 0, 4 ) == "VCAL" ) {
00142 ICalTimeZone zone = tzlist->zone( (*it)->dtStart().timeZone().name() );
00143 if ( zone.isValid() ) {
00144 QByteArray timezone = zone.vtimezone();
00145 addPropValue( vcal, VCTimeZoneProp, parseTZ( timezone ).toLocal8Bit() );
00146 QString dst = parseDst( timezone );
00147 while ( !dst.isEmpty() ) {
00148 addPropValue( vcal, VCDayLightProp, dst.toLocal8Bit() );
00149 dst = parseDst( timezone );
00150 }
00151 }
00152 }
00153 vo = eventToVTodo( *it );
00154 addVObjectProp( vcal, vo );
00155 }
00156
00157 Event::List events = d->mCalendar->rawEvents();
00158 Event::List::ConstIterator it2;
00159 for ( it2 = events.constBegin(); it2 != events.constEnd(); ++it2 ) {
00160 if ( (*it2)->dtStart().timeZone().name().mid( 0, 4 ) == "VCAL" ) {
00161 ICalTimeZone zone = tzlist->zone( (*it2)->dtStart().timeZone().name() );
00162 if ( zone.isValid() ) {
00163 QByteArray timezone = zone.vtimezone();
00164 addPropValue( vcal, VCTimeZoneProp, parseTZ( timezone ).toLocal8Bit() );
00165 QString dst = parseDst( timezone );
00166 while ( !dst.isEmpty() ) {
00167 addPropValue( vcal, VCDayLightProp, dst.toLocal8Bit() );
00168 dst = parseDst( timezone );
00169 }
00170 }
00171 }
00172 vo = eventToVEvent( *it2 );
00173 addVObjectProp( vcal, vo );
00174 }
00175 writeVObjectToFile( QFile::encodeName( fileName ).data(), vcal );
00176 cleanVObjects( vcal );
00177 cleanStrTbl();
00178
00179 if ( QFile::exists( fileName ) ) {
00180 return true;
00181 } else {
00182 return false;
00183 }
00184
00185 return false;
00186 }
00187
00188 bool VCalFormat::fromString( const Calendar::Ptr &calendar, const QString &string,
00189 bool deleted, const QString ¬ebook )
00190 {
00191 return fromRawString( calendar, string.toUtf8(), deleted, notebook );
00192 }
00193
00194 bool VCalFormat::fromRawString( const Calendar::Ptr &calendar, const QByteArray &string,
00195 bool deleted, const QString ¬ebook )
00196 {
00197 d->mCalendar = calendar;
00198
00199 if ( !string.size() ) {
00200 return false;
00201 }
00202
00203 VObject *vcal = Parse_MIME( string.data(), string.size() );
00204 if ( !vcal ) {
00205 return false;
00206 }
00207
00208 VObjectIterator i;
00209 initPropIterator( &i, vcal );
00210
00211
00212 QString savedTimeZoneId = d->mCalendar->timeZoneId();
00213 populate( vcal, deleted, notebook );
00214 d->mCalendar->setTimeZoneId(savedTimeZoneId);
00215
00216
00217 cleanVObjects( vcal );
00218 cleanStrTbl();
00219
00220 return true;
00221 }
00222
00223 QString VCalFormat::toString( const Calendar::Ptr &calendar,
00224 const QString ¬ebook, bool deleted )
00225 {
00226
00227 d->mCalendar = calendar;
00228
00229 ICalTimeZones *tzlist = d->mCalendar->timeZones();
00230
00231 VObject *vo;
00232 VObject *vcal = newVObject( VCCalProp );
00233
00234 addPropValue( vcal, VCProdIdProp, CalFormat::productId().toLatin1() );
00235 addPropValue( vcal, VCVersionProp, _VCAL_VERSION );
00236
00237
00238 Todo::List todoList = deleted ? d->mCalendar->deletedTodos() : d->mCalendar->rawTodos();
00239 Todo::List::ConstIterator it;
00240 for ( it = todoList.constBegin(); it != todoList.constEnd(); ++it ) {
00241 if ( !deleted || !d->mCalendar->todo( (*it)->uid(), (*it)->recurrenceId() ) ) {
00242
00243 if ( notebook.isEmpty() ||
00244 ( !calendar->notebook(*it).isEmpty() &&
00245 notebook.endsWith( calendar->notebook( *it ) ) ) ) {
00246 if ( (*it)->dtStart().timeZone().name().mid( 0, 4 ) == "VCAL" ) {
00247 ICalTimeZone zone = tzlist->zone( (*it)->dtStart().timeZone().name() );
00248 if ( zone.isValid() ) {
00249 QByteArray timezone = zone.vtimezone();
00250 addPropValue( vcal, VCTimeZoneProp, parseTZ( timezone ).toLocal8Bit() );
00251 QString dst = parseDst( timezone );
00252 while ( !dst.isEmpty() ) {
00253 addPropValue( vcal, VCDayLightProp, dst.toLocal8Bit() );
00254 dst = parseDst( timezone );
00255 }
00256 }
00257 }
00258 vo = eventToVTodo( *it );
00259 addVObjectProp( vcal, vo );
00260 }
00261 }
00262 }
00263
00264
00265 Event::List events = deleted ? d->mCalendar->deletedEvents() : d->mCalendar->rawEvents();
00266 Event::List::ConstIterator it2;
00267 for ( it2 = events.constBegin(); it2 != events.constEnd(); ++it2 ) {
00268 if ( !deleted || !d->mCalendar->event( (*it2)->uid(), (*it2)->recurrenceId() ) ) {
00269
00270 if ( notebook.isEmpty() ||
00271 ( !calendar->notebook( *it2 ).isEmpty() &&
00272 notebook.endsWith( calendar->notebook( *it2 ) ) ) ) {
00273 if ( (*it2)->dtStart().timeZone().name().mid( 0, 4 ) == "VCAL" ) {
00274 ICalTimeZone zone = tzlist->zone( (*it2)->dtStart().timeZone().name() );
00275 if ( zone.isValid() ) {
00276 QByteArray timezone = zone.vtimezone();
00277 addPropValue( vcal, VCTimeZoneProp, parseTZ( timezone ).toLocal8Bit() );
00278 QString dst = parseDst( timezone );
00279 while ( !dst.isEmpty() ) {
00280 addPropValue( vcal, VCDayLightProp, dst.toLocal8Bit() );
00281 dst = parseDst( timezone );
00282 }
00283 }
00284 }
00285 vo = eventToVEvent( *it2 );
00286 addVObjectProp( vcal, vo );
00287 }
00288 }
00289 }
00290
00291 char *buf = writeMemVObject( 0, 0, vcal );
00292
00293 QString result( buf );
00294
00295 deleteStr( buf );
00296
00297 cleanVObject( vcal );
00298
00299 return result;
00300 }
00301
00302 VObject *VCalFormat::eventToVTodo( const Todo::Ptr &anEvent )
00303 {
00304 VObject *vtodo;
00305 QString tmpStr;
00306
00307 vtodo = newVObject( VCTodoProp );
00308
00309
00310 if ( anEvent->hasDueDate() ) {
00311 tmpStr = kDateTimeToISO( anEvent->dtDue(), !anEvent->allDay() );
00312 addPropValue( vtodo, VCDueProp, tmpStr.toLocal8Bit() );
00313 }
00314
00315
00316 if ( anEvent->hasStartDate() ) {
00317 tmpStr = kDateTimeToISO( anEvent->dtStart(), !anEvent->allDay() );
00318 addPropValue( vtodo, VCDTstartProp, tmpStr.toLocal8Bit() );
00319 }
00320
00321
00322 tmpStr = kDateTimeToISO( anEvent->created() );
00323 addPropValue( vtodo, VCDCreatedProp, tmpStr.toLocal8Bit() );
00324
00325
00326 addPropValue( vtodo, VCUniqueStringProp,
00327 anEvent->uid().toLocal8Bit() );
00328
00329
00330 tmpStr.sprintf( "%i", anEvent->revision() );
00331 addPropValue( vtodo, VCSequenceProp, tmpStr.toLocal8Bit() );
00332
00333
00334 tmpStr = kDateTimeToISO( anEvent->lastModified() );
00335 addPropValue( vtodo, VCLastModifiedProp, tmpStr.toLocal8Bit() );
00336
00337
00338
00339 if ( !anEvent->organizer()->email().isEmpty() ) {
00340 tmpStr = "MAILTO:" + anEvent->organizer()->email();
00341 addPropValue( vtodo, ICOrganizerProp, tmpStr.toLocal8Bit() );
00342 }
00343
00344
00345 if ( anEvent->attendeeCount() > 0 ) {
00346 Attendee::List::ConstIterator it;
00347 Attendee::Ptr curAttendee;
00348 for ( it = anEvent->attendees().constBegin(); it != anEvent->attendees().constEnd();
00349 ++it ) {
00350 curAttendee = *it;
00351 if ( !curAttendee->email().isEmpty() && !curAttendee->name().isEmpty() ) {
00352 tmpStr = "MAILTO:" + curAttendee->name() + " <" + curAttendee->email() + '>';
00353 } else if ( curAttendee->name().isEmpty() && curAttendee->email().isEmpty() ) {
00354 tmpStr = "MAILTO: ";
00355 kDebug() << "warning! this Event has an attendee w/o name or email!";
00356 } else if ( curAttendee->name().isEmpty() ) {
00357 tmpStr = "MAILTO: " + curAttendee->email();
00358 } else {
00359 tmpStr = "MAILTO: " + curAttendee->name();
00360 }
00361 VObject *aProp = addPropValue( vtodo, VCAttendeeProp, tmpStr.toLocal8Bit() );
00362 addPropValue( aProp, VCRSVPProp, curAttendee->RSVP() ? "TRUE" : "FALSE" );
00363 addPropValue( aProp, VCStatusProp, writeStatus( curAttendee->status() ) );
00364 }
00365 }
00366
00367
00368 if ( !anEvent->description().isEmpty() ) {
00369 VObject *d = addPropValue( vtodo, VCDescriptionProp,
00370 anEvent->description().toLocal8Bit() );
00371 if ( anEvent->description().indexOf( '\n' ) != -1 ) {
00372 addPropValue( d, VCEncodingProp, VCQuotedPrintableProp );
00373 }
00374 }
00375
00376
00377 if ( !anEvent->summary().isEmpty() ) {
00378 addPropValue( vtodo, VCSummaryProp, anEvent->summary().toLocal8Bit() );
00379 }
00380
00381
00382 if ( !anEvent->location().isEmpty() ) {
00383 addPropValue( vtodo, VCLocationProp, anEvent->location().toLocal8Bit() );
00384 }
00385
00386
00387
00388 addPropValue( vtodo, VCStatusProp, anEvent->isCompleted() ? "COMPLETED" : "NEEDS ACTION" );
00389
00390
00391 if ( anEvent->hasCompletedDate() ) {
00392 tmpStr = kDateTimeToISO( anEvent->completed() );
00393 addPropValue( vtodo, VCCompletedProp, tmpStr.toLocal8Bit() );
00394 }
00395
00396
00397 tmpStr.sprintf( "%i", anEvent->priority() );
00398 addPropValue( vtodo, VCPriorityProp, tmpStr.toLocal8Bit() );
00399
00400
00401 if ( !anEvent->relatedTo().isEmpty() ) {
00402 addPropValue( vtodo, VCRelatedToProp,
00403 anEvent->relatedTo().toLocal8Bit() );
00404 }
00405
00406
00407 const char *text = 0;
00408 switch ( anEvent->secrecy() ) {
00409 case Incidence::SecrecyPublic:
00410 text = "PUBLIC";
00411 break;
00412 case Incidence::SecrecyPrivate:
00413 text = "PRIVATE";
00414 break;
00415 case Incidence::SecrecyConfidential:
00416 text = "CONFIDENTIAL";
00417 break;
00418 }
00419 if ( text ) {
00420 addPropValue( vtodo, VCClassProp, text );
00421 }
00422
00423
00424 const QStringList tmpStrList = anEvent->categories();
00425 tmpStr = "";
00426 QString catStr;
00427 QStringList::const_iterator its;
00428 for ( its = tmpStrList.constBegin(); its != tmpStrList.constEnd(); ++its ) {
00429 catStr = *its;
00430 if ( catStr[0] == ' ' ) {
00431 tmpStr += catStr.mid( 1 );
00432 } else {
00433 tmpStr += catStr;
00434 }
00435
00436
00437
00438 tmpStr += ';';
00439 }
00440 if ( !tmpStr.isEmpty() ) {
00441 tmpStr.truncate( tmpStr.length() - 1 );
00442 addPropValue( vtodo, VCCategoriesProp, tmpStr.toLocal8Bit() );
00443 }
00444
00445
00446 Alarm::List::ConstIterator it;
00447 for ( it = anEvent->alarms().constBegin(); it != anEvent->alarms().constEnd(); ++it ) {
00448 Alarm::Ptr alarm = *it;
00449 if ( alarm->enabled() ) {
00450 VObject *a;
00451 if ( alarm->type() == Alarm::Display ) {
00452 a = addProp( vtodo, VCDAlarmProp );
00453 tmpStr = kDateTimeToISO( alarm->time() );
00454 addPropValue( a, VCRunTimeProp, tmpStr.toLocal8Bit() );
00455 addPropValue( a, VCRepeatCountProp, "1" );
00456 if ( alarm->text().isNull() ) {
00457 addPropValue( a, VCDisplayStringProp, "beep!" );
00458 } else {
00459 addPropValue( a, VCDisplayStringProp, alarm->text().toAscii().data() );
00460 }
00461 } else if ( alarm->type() == Alarm::Audio ) {
00462 a = addProp( vtodo, VCAAlarmProp );
00463 tmpStr = kDateTimeToISO( alarm->time() );
00464 addPropValue( a, VCRunTimeProp, tmpStr.toLocal8Bit() );
00465 addPropValue( a, VCRepeatCountProp, "1" );
00466 addPropValue( a, VCAudioContentProp, QFile::encodeName( alarm->audioFile() ) );
00467 } else if ( alarm->type() == Alarm::Procedure ) {
00468 a = addProp( vtodo, VCPAlarmProp );
00469 tmpStr = kDateTimeToISO( alarm->time() );
00470 addPropValue( a, VCRunTimeProp, tmpStr.toLocal8Bit() );
00471 addPropValue( a, VCRepeatCountProp, "1" );
00472 addPropValue( a, VCProcedureNameProp, QFile::encodeName( alarm->programFile() ) );
00473 }
00474 }
00475 }
00476
00477 QString pilotId = anEvent->nonKDECustomProperty( KPilotIdProp );
00478 if ( !pilotId.isEmpty() ) {
00479
00480 addPropValue( vtodo, KPilotIdProp, pilotId.toLocal8Bit() );
00481 addPropValue( vtodo, KPilotStatusProp,
00482 anEvent->nonKDECustomProperty( KPilotStatusProp ).toLocal8Bit() );
00483 }
00484 #if defined(KCALCORE_FOR_SYMBIAN)
00485 if ( anEvent->nonKDECustomProperty( EPOCAgendaEntryTypeProp ).isEmpty() ) {
00486
00487
00488 addPropValue( vtodo, EPOCAgendaEntryTypeProp, "TODO" );
00489 }
00490
00491 writeCustomProperties( vtodo, anEvent );
00492 #endif
00493
00494 return vtodo;
00495 }
00496
00497 VObject *VCalFormat::eventToVEvent( const Event::Ptr &anEvent )
00498 {
00499 VObject *vevent;
00500 QString tmpStr;
00501
00502 vevent = newVObject( VCEventProp );
00503
00504
00505 tmpStr = kDateTimeToISO( anEvent->dtStart(), !anEvent->allDay() );
00506 addPropValue( vevent, VCDTstartProp, tmpStr.toLocal8Bit() );
00507
00508 #if !defined(KCALCORE_FOR_MEEGO)
00509
00510
00511 if ( anEvent->dtStart() != anEvent->dtEnd() ) {
00512 tmpStr = kDateTimeToISO( anEvent->dtEnd(), !anEvent->allDay() );
00513 addPropValue( vevent, VCDTendProp, tmpStr.toLocal8Bit() );
00514 }
00515 #else
00516
00517 tmpStr = kDateTimeToISO( anEvent->dtEnd(), !anEvent->allDay() );
00518 addPropValue( vevent, VCDTendProp, tmpStr.toLocal8Bit() );
00519 #endif
00520
00521
00522 tmpStr = kDateTimeToISO( anEvent->created() );
00523 addPropValue( vevent, VCDCreatedProp, tmpStr.toLocal8Bit() );
00524
00525
00526 addPropValue( vevent, VCUniqueStringProp,
00527 anEvent->uid().toLocal8Bit() );
00528
00529
00530 tmpStr.sprintf( "%i", anEvent->revision() );
00531 addPropValue( vevent, VCSequenceProp, tmpStr.toLocal8Bit() );
00532
00533
00534 tmpStr = kDateTimeToISO( anEvent->lastModified() );
00535 addPropValue( vevent, VCLastModifiedProp, tmpStr.toLocal8Bit() );
00536
00537
00538
00539 if ( !anEvent->organizer()->email().isEmpty() ) {
00540 tmpStr = "MAILTO:" + anEvent->organizer()->email();
00541 addPropValue( vevent, ICOrganizerProp, tmpStr.toLocal8Bit() );
00542 }
00543
00544
00545 if ( anEvent->attendeeCount() > 0 ) {
00546 Attendee::List::ConstIterator it;
00547 for ( it = anEvent->attendees().constBegin(); it != anEvent->attendees().constEnd();
00548 ++it ) {
00549 Attendee::Ptr curAttendee = *it;
00550 if ( !curAttendee->email().isEmpty() && !curAttendee->name().isEmpty() ) {
00551 tmpStr = "MAILTO:" + curAttendee->name() + " <" + curAttendee->email() + '>';
00552 } else if ( curAttendee->name().isEmpty() && curAttendee->email().isEmpty() ) {
00553 tmpStr = "MAILTO: ";
00554 kDebug() << "warning! this Event has an attendee w/o name or email!";
00555 } else if ( curAttendee->name().isEmpty() ) {
00556 tmpStr = "MAILTO: " + curAttendee->email();
00557 } else {
00558 tmpStr = "MAILTO: " + curAttendee->name();
00559 }
00560 VObject *aProp = addPropValue( vevent, VCAttendeeProp, tmpStr.toLocal8Bit() );
00561 addPropValue( aProp, VCRSVPProp, curAttendee->RSVP() ? "TRUE" : "FALSE" );
00562 addPropValue( aProp, VCStatusProp, writeStatus( curAttendee->status() ) );
00563 }
00564 }
00565
00566
00567 const Recurrence *recur = anEvent->recurrence();
00568 if ( recur->recurs() ) {
00569 bool validRecur = true;
00570 QString tmpStr2;
00571 switch ( recur->recurrenceType() ) {
00572 case Recurrence::rDaily:
00573 tmpStr.sprintf( "D%i ", recur->frequency() );
00574 break;
00575 case Recurrence::rWeekly:
00576 tmpStr.sprintf( "W%i ", recur->frequency() );
00577 for ( int i = 0; i < 7; ++i ) {
00578 QBitArray days ( recur->days() );
00579 if ( days.testBit(i) ) {
00580 tmpStr += dayFromNum( i );
00581 }
00582 }
00583 break;
00584 case Recurrence::rMonthlyPos:
00585 {
00586 tmpStr.sprintf( "MP%i ", recur->frequency() );
00587
00588 QList<RecurrenceRule::WDayPos> tmpPositions = recur->monthPositions();
00589 for ( QList<RecurrenceRule::WDayPos>::ConstIterator posit = tmpPositions.constBegin();
00590 posit != tmpPositions.constEnd(); ++posit ) {
00591 int pos = (*posit).pos();
00592 tmpStr2.sprintf( "%i", ( pos > 0 ) ? pos : (-pos) );
00593 if ( pos < 0 ) {
00594 tmpStr2 += "- ";
00595 } else {
00596 tmpStr2 += "+ ";
00597 }
00598 tmpStr += tmpStr2;
00599 tmpStr += dayFromNum( (*posit).day() - 1 );
00600 }
00601 break;
00602 }
00603 case Recurrence::rMonthlyDay:
00604 {
00605 tmpStr.sprintf( "MD%i ", recur->frequency() );
00606
00607 const QList<int> tmpDays = recur->monthDays();
00608 for ( QList<int>::ConstIterator tmpDay = tmpDays.constBegin();
00609 tmpDay != tmpDays.constEnd(); ++tmpDay ) {
00610 tmpStr2.sprintf( "%i ", *tmpDay );
00611 tmpStr += tmpStr2;
00612 }
00613 break;
00614 }
00615 case Recurrence::rYearlyMonth:
00616 {
00617 tmpStr.sprintf( "YM%i ", recur->frequency() );
00618
00619
00620 const QList<int> months = recur->yearMonths();
00621 for ( QList<int>::ConstIterator mit = months.constBegin();
00622 mit != months.constEnd(); ++mit ) {
00623 tmpStr2.sprintf( "%i ", *mit );
00624 tmpStr += tmpStr2;
00625 }
00626 break;
00627 }
00628 case Recurrence::rYearlyDay:
00629 {
00630 tmpStr.sprintf( "YD%i ", recur->frequency() );
00631
00632 const QList<int> tmpDays = recur->yearDays();
00633 for ( QList<int>::ConstIterator tmpDay = tmpDays.begin();
00634 tmpDay != tmpDays.end(); ++tmpDay ) {
00635 tmpStr2.sprintf( "%i ", *tmpDay );
00636 tmpStr += tmpStr2;
00637 }
00638 break;
00639 }
00640 default:
00641
00642 kDebug() << "ERROR, it should never get here in eventToVEvent!";
00643 validRecur = false;
00644 break;
00645 }
00646
00647 if ( recur->duration() > 0 ) {
00648 tmpStr2.sprintf( "#%i", recur->duration() );
00649 tmpStr += tmpStr2;
00650 } else if ( recur->duration() == -1 ) {
00651 tmpStr += "#0";
00652 } else {
00653 #if !defined(KCALCORE_FOR_MEEGO)
00654 tmpStr += kDateTimeToISO( recur->endDateTime(), false );
00655 #else
00656 tmpStr +=
00657 kDateTimeToISO( recur->endDateTime().toTimeSpec( d->mCalendar->timeSpec() ), false );
00658 #endif
00659 }
00660
00661
00662 if ( validRecur ) {
00663 addPropValue( vevent, VCRRuleProp, tmpStr.toLocal8Bit() );
00664 }
00665
00666 }
00667
00668
00669 DateList dateList = recur->exDates();
00670 DateList::ConstIterator it;
00671 QString tmpStr2;
00672
00673 for ( it = dateList.constBegin(); it != dateList.constEnd(); ++it ) {
00674 tmpStr = qDateToISO(*it) + ';';
00675 tmpStr2 += tmpStr;
00676 }
00677 if ( !tmpStr2.isEmpty() ) {
00678 tmpStr2.truncate( tmpStr2.length() - 1 );
00679 addPropValue( vevent, VCExpDateProp, tmpStr2.toLocal8Bit() );
00680 }
00681
00682 DateTimeList dateTimeList = recur->exDateTimes();
00683 DateTimeList::ConstIterator idt;
00684 tmpStr2.clear();
00685
00686 for ( idt = dateTimeList.constBegin(); idt != dateTimeList.constEnd(); ++idt ) {
00687 tmpStr = kDateTimeToISO( *idt ) + ';';
00688 tmpStr2 += tmpStr;
00689 }
00690 if ( !tmpStr2.isEmpty() ) {
00691 tmpStr2.truncate( tmpStr2.length() - 1 );
00692 addPropValue( vevent, VCExpDateProp, tmpStr2.toLocal8Bit() );
00693 }
00694
00695
00696 if ( !anEvent->description().isEmpty() ) {
00697 VObject *d = addPropValue( vevent, VCDescriptionProp,
00698 anEvent->description().toLocal8Bit() );
00699 if ( anEvent->description().indexOf( '\n' ) != -1 ) {
00700 addPropValue( d, VCEncodingProp, VCQuotedPrintableProp );
00701 }
00702 }
00703
00704
00705 if ( !anEvent->summary().isEmpty() ) {
00706 addPropValue( vevent, VCSummaryProp, anEvent->summary().toLocal8Bit() );
00707 }
00708
00709
00710 if ( !anEvent->location().isEmpty() ) {
00711 addPropValue( vevent, VCLocationProp, anEvent->location().toLocal8Bit() );
00712 }
00713
00714
00715
00716
00717
00718
00719 const char *text = 0;
00720 switch ( anEvent->secrecy() ) {
00721 case Incidence::SecrecyPublic:
00722 text = "PUBLIC";
00723 break;
00724 case Incidence::SecrecyPrivate:
00725 text = "PRIVATE";
00726 break;
00727 case Incidence::SecrecyConfidential:
00728 text = "CONFIDENTIAL";
00729 break;
00730 }
00731 if ( text ) {
00732 addPropValue( vevent, VCClassProp, text );
00733 }
00734
00735
00736 QStringList tmpStrList = anEvent->categories();
00737 tmpStr = "";
00738 QString catStr;
00739 for ( QStringList::const_iterator it = tmpStrList.constBegin(); it != tmpStrList.constEnd();
00740 ++it ) {
00741 catStr = *it;
00742 if ( catStr[0] == ' ' ) {
00743 tmpStr += catStr.mid( 1 );
00744 } else {
00745 tmpStr += catStr;
00746 }
00747
00748
00749
00750 tmpStr += ';';
00751 }
00752 if ( !tmpStr.isEmpty() ) {
00753 tmpStr.truncate( tmpStr.length() - 1 );
00754 addPropValue( vevent, VCCategoriesProp, tmpStr.toLocal8Bit() );
00755 }
00756
00757
00758
00759 Attachment::List attachments = anEvent->attachments();
00760 Attachment::List::ConstIterator atIt;
00761 for ( atIt = attachments.constBegin(); atIt != attachments.constEnd(); ++atIt ) {
00762 addPropValue( vevent, VCAttachProp, (*atIt)->uri().toLocal8Bit() );
00763 }
00764
00765
00766 tmpStrList = anEvent->resources();
00767 tmpStr = tmpStrList.join( ";" );
00768 if ( !tmpStr.isEmpty() ) {
00769 addPropValue( vevent, VCResourcesProp, tmpStr.toLocal8Bit() );
00770 }
00771
00772
00773 Alarm::List::ConstIterator it2;
00774 for ( it2 = anEvent->alarms().constBegin(); it2 != anEvent->alarms().constEnd(); ++it2 ) {
00775 Alarm::Ptr alarm = *it2;
00776 if ( alarm->enabled() ) {
00777 VObject *a;
00778 if ( alarm->type() == Alarm::Display ) {
00779 a = addProp( vevent, VCDAlarmProp );
00780 tmpStr = kDateTimeToISO( alarm->time() );
00781 addPropValue( a, VCRunTimeProp, tmpStr.toLocal8Bit() );
00782 addPropValue( a, VCRepeatCountProp, "1" );
00783 if ( alarm->text().isNull() ) {
00784 addPropValue( a, VCDisplayStringProp, "beep!" );
00785 } else {
00786 addPropValue( a, VCDisplayStringProp, alarm->text().toAscii().data() );
00787 }
00788 } else if ( alarm->type() == Alarm::Audio ) {
00789 a = addProp( vevent, VCAAlarmProp );
00790 tmpStr = kDateTimeToISO( alarm->time() );
00791 addPropValue( a, VCRunTimeProp, tmpStr.toLocal8Bit() );
00792 addPropValue( a, VCRepeatCountProp, "1" );
00793 addPropValue( a, VCAudioContentProp, QFile::encodeName( alarm->audioFile() ) );
00794 }
00795 if ( alarm->type() == Alarm::Procedure ) {
00796 a = addProp( vevent, VCPAlarmProp );
00797 tmpStr = kDateTimeToISO( alarm->time() );
00798 addPropValue( a, VCRunTimeProp, tmpStr.toLocal8Bit() );
00799 addPropValue( a, VCRepeatCountProp, "1" );
00800 addPropValue( a, VCProcedureNameProp, QFile::encodeName( alarm->programFile() ) );
00801 }
00802 }
00803 }
00804
00805
00806 tmpStr.sprintf( "%i", anEvent->priority() );
00807 addPropValue( vevent, VCPriorityProp, tmpStr.toLocal8Bit() );
00808
00809
00810 tmpStr.sprintf( "%i", anEvent->transparency() );
00811 addPropValue( vevent, VCTranspProp, tmpStr.toLocal8Bit() );
00812
00813
00814 if ( !anEvent->relatedTo().isEmpty() ) {
00815 addPropValue( vevent, VCRelatedToProp, anEvent->relatedTo().toLocal8Bit() );
00816 }
00817
00818 QString pilotId = anEvent->nonKDECustomProperty( KPilotIdProp );
00819 if ( !pilotId.isEmpty() ) {
00820
00821 addPropValue( vevent, KPilotIdProp, pilotId.toLocal8Bit() );
00822 addPropValue( vevent, KPilotStatusProp,
00823 anEvent->nonKDECustomProperty( KPilotStatusProp ).toLocal8Bit() );
00824 }
00825
00826 #if defined(KCALCORE_FOR_SYMBIAN)
00827 if ( anEvent->nonKDECustomProperty( EPOCAgendaEntryTypeProp ).isEmpty() ) {
00828
00829
00830 if ( anEvent->allDay() ) {
00831 addPropValue( vevent, EPOCAgendaEntryTypeProp, "EVENT" );
00832 } else {
00833 addPropValue( vevent, EPOCAgendaEntryTypeProp, "APPOINTMENT" );
00834 }
00835 }
00836
00837 if ( anEvent->hasRecurrenceId() ) {
00838 tmpStr = kDateTimeToISO( anEvent->recurrenceId(), true );
00839 addPropValue( vevent, VCRecurrenceIdProp, tmpStr.toLocal8Bit() );
00840 }
00841 writeCustomProperties( vevent, anEvent );
00842 #endif
00843
00844 return vevent;
00845 }
00846
00847 Todo::Ptr VCalFormat::VTodoToEvent( VObject *vtodo )
00848 {
00849 VObject *vo;
00850 VObjectIterator voi;
00851 char *s;
00852
00853 Todo::Ptr anEvent( new Todo );
00854
00855
00856 if ( ( vo = isAPropertyOf( vtodo, VCDCreatedProp ) ) != 0 ) {
00857 anEvent->setCreated( ISOToKDateTime( s = fakeCString( vObjectUStringZValue( vo ) ) ) );
00858 deleteStr( s );
00859 }
00860
00861
00862 vo = isAPropertyOf( vtodo, VCUniqueStringProp );
00863
00864
00865 if ( vo ) {
00866 anEvent->setUid( s = fakeCString( vObjectUStringZValue( vo ) ) );
00867 deleteStr( s );
00868 }
00869
00870
00871 if ( ( vo = isAPropertyOf( vtodo, VCLastModifiedProp ) ) != 0 ) {
00872 anEvent->setLastModified( ISOToKDateTime( s = fakeCString( vObjectUStringZValue( vo ) ) ) );
00873 deleteStr( s );
00874 } else {
00875 anEvent->setLastModified( KDateTime::currentUtcDateTime() );
00876 }
00877
00878
00879
00880 if ( ( vo = isAPropertyOf( vtodo, ICOrganizerProp ) ) != 0 ) {
00881 anEvent->setOrganizer( s = fakeCString( vObjectUStringZValue( vo ) ) );
00882 deleteStr( s );
00883 } else {
00884 if ( d->mCalendar->owner()->name() != "Unknown Name" ) {
00885 anEvent->setOrganizer( d->mCalendar->owner() );
00886 }
00887 }
00888
00889
00890 initPropIterator( &voi, vtodo );
00891 while ( moreIteration( &voi ) ) {
00892 vo = nextVObject( &voi );
00893 if ( strcmp( vObjectName( vo ), VCAttendeeProp ) == 0 ) {
00894 Attendee::Ptr a;
00895 VObject *vp;
00896 s = fakeCString( vObjectUStringZValue( vo ) );
00897 QString tmpStr = QString::fromLocal8Bit( s );
00898 deleteStr( s );
00899 tmpStr = tmpStr.simplified();
00900 int emailPos1, emailPos2;
00901 if ( ( emailPos1 = tmpStr.indexOf( '<' ) ) > 0 ) {
00902
00903 emailPos2 = tmpStr.lastIndexOf( '>' );
00904 a = Attendee::Ptr( new Attendee( tmpStr.left( emailPos1 - 1 ),
00905 tmpStr.mid( emailPos1 + 1,
00906 emailPos2 - ( emailPos1 + 1 ) ) ) );
00907 } else if ( tmpStr.indexOf( '@' ) > 0 ) {
00908
00909 a = Attendee::Ptr( new Attendee( 0, tmpStr ) );
00910 } else {
00911
00912
00913 QString email = tmpStr.replace( ' ', '.' );
00914 a = Attendee::Ptr( new Attendee( tmpStr, email ) );
00915 }
00916
00917
00918 if ( ( vp = isAPropertyOf( vo, VCRSVPProp ) ) != 0 ) {
00919 a->setRSVP( vObjectStringZValue( vp ) );
00920 }
00921
00922 if ( ( vp = isAPropertyOf( vo, VCStatusProp ) ) != 0 ) {
00923 a->setStatus( readStatus( vObjectStringZValue( vp ) ) );
00924 }
00925
00926 anEvent->addAttendee( a );
00927 }
00928 }
00929
00930
00931 if ( ( vo = isAPropertyOf( vtodo, VCDescriptionProp ) ) != 0 ) {
00932 s = fakeCString( vObjectUStringZValue( vo ) );
00933 anEvent->setDescription( QString::fromLocal8Bit( s ), Qt::mightBeRichText( s ) );
00934 deleteStr( s );
00935 }
00936
00937
00938 if ( ( vo = isAPropertyOf( vtodo, VCSummaryProp ) ) ) {
00939 s = fakeCString( vObjectUStringZValue( vo ) );
00940 anEvent->setSummary( QString::fromLocal8Bit( s ), Qt::mightBeRichText( s ) );
00941 deleteStr( s );
00942 }
00943
00944
00945 if ( ( vo = isAPropertyOf( vtodo, VCLocationProp ) ) != 0 ) {
00946 s = fakeCString( vObjectUStringZValue( vo ) );
00947 anEvent->setLocation( QString::fromLocal8Bit( s ), Qt::mightBeRichText( s ) );
00948 deleteStr( s );
00949 }
00950
00951
00952
00953 if ( ( vo = isAPropertyOf( vtodo, VCStatusProp ) ) != 0 ) {
00954 s = fakeCString( vObjectUStringZValue( vo ) );
00955 if ( s && strcmp( s, "COMPLETED" ) == 0 ) {
00956 anEvent->setCompleted( true );
00957 } else {
00958 anEvent->setCompleted( false );
00959 }
00960 deleteStr( s );
00961 } else {
00962 anEvent->setCompleted( false );
00963 }
00964
00965
00966 if ( ( vo = isAPropertyOf( vtodo, VCCompletedProp ) ) != 0 ) {
00967 anEvent->setCompleted( ISOToKDateTime( s = fakeCString( vObjectUStringZValue( vo ) ) ) );
00968 deleteStr( s );
00969 }
00970
00971
00972 if ( ( vo = isAPropertyOf( vtodo, VCPriorityProp ) ) ) {
00973 s = fakeCString( vObjectUStringZValue( vo ) );
00974 if ( s ) {
00975 anEvent->setPriority( atoi( s ) );
00976 deleteStr( s );
00977 }
00978 }
00979
00980 anEvent->setAllDay( false );
00981
00982
00983 if ( ( vo = isAPropertyOf( vtodo, VCDueProp ) ) != 0 ) {
00984 anEvent->setDtDue( ISOToKDateTime( s = fakeCString( vObjectUStringZValue( vo ) ) ) );
00985 deleteStr( s );
00986 anEvent->setHasDueDate( true );
00987 if ( anEvent->dtDue().time().hour() == 0 &&
00988 anEvent->dtDue().time().minute() == 0 &&
00989 anEvent->dtDue().time().second() == 0 ) {
00990 anEvent->setAllDay( true );
00991 }
00992 } else {
00993 anEvent->setHasDueDate( false );
00994 }
00995
00996
00997 if ( ( vo = isAPropertyOf( vtodo, VCDTstartProp ) ) != 0 ) {
00998 anEvent->setDtStart( ISOToKDateTime( s = fakeCString( vObjectUStringZValue( vo ) ) ) );
00999 deleteStr( s );
01000 anEvent->setHasStartDate( true );
01001 if ( anEvent->dtStart().time().hour() == 0 &&
01002 anEvent->dtStart().time().minute() == 0 &&
01003 anEvent->dtStart().time().second() == 0 ) {
01004 anEvent->setAllDay( true );
01005 }
01006 } else {
01007 anEvent->setHasStartDate( false );
01008 }
01009
01010
01011 if ( ( vo = isAPropertyOf( vtodo, VCDAlarmProp ) ) ) {
01012 Alarm::Ptr alarm;
01013 VObject *a;
01014 VObject *b;
01015 a = isAPropertyOf( vo, VCRunTimeProp );
01016 b = isAPropertyOf( vo, VCDisplayStringProp );
01017
01018 if ( a || b ) {
01019 alarm = anEvent->newAlarm();
01020 if ( a ) {
01021 alarm->setTime( ISOToKDateTime( s = fakeCString( vObjectUStringZValue( a ) ) ) );
01022 deleteStr( s );
01023 }
01024 alarm->setEnabled( true );
01025 if ( b ) {
01026 s = fakeCString( vObjectUStringZValue( b ) );
01027 alarm->setDisplayAlarm( QString( s ) );
01028 deleteStr( s );
01029 } else {
01030 alarm->setDisplayAlarm( QString() );
01031 }
01032 }
01033 }
01034
01035 if ( ( vo = isAPropertyOf( vtodo, VCAAlarmProp ) ) ) {
01036 Alarm::Ptr alarm;
01037 VObject *a;
01038 VObject *b;
01039 a = isAPropertyOf( vo, VCRunTimeProp );
01040 b = isAPropertyOf( vo, VCAudioContentProp );
01041
01042 if ( a || b ) {
01043 alarm = anEvent->newAlarm();
01044 if ( a ) {
01045 alarm->setTime( ISOToKDateTime( s = fakeCString( vObjectUStringZValue( a ) ) ) );
01046 deleteStr( s );
01047 }
01048 alarm->setEnabled( true );
01049 if ( b ) {
01050 s = fakeCString( vObjectUStringZValue( b ) );
01051 alarm->setAudioAlarm( QFile::decodeName( s ) );
01052 deleteStr( s );
01053 } else {
01054 alarm->setAudioAlarm( QString() );
01055 }
01056 }
01057 }
01058
01059 if ( ( vo = isAPropertyOf( vtodo, VCPAlarmProp ) ) ) {
01060 Alarm::Ptr alarm;
01061 VObject *a;
01062 VObject *b;
01063 a = isAPropertyOf( vo, VCRunTimeProp );
01064 b = isAPropertyOf( vo, VCProcedureNameProp );
01065
01066 if ( a || b ) {
01067 alarm = anEvent->newAlarm();
01068 if ( a ) {
01069 alarm->setTime( ISOToKDateTime( s = fakeCString( vObjectUStringZValue( a ) ) ) );
01070 deleteStr( s );
01071 }
01072 alarm->setEnabled( true );
01073
01074 if ( b ) {
01075 s = fakeCString( vObjectUStringZValue( b ) );
01076 alarm->setProcedureAlarm( QFile::decodeName( s ) );
01077 deleteStr( s );
01078 } else {
01079 alarm->setProcedureAlarm( QString() );
01080 }
01081 }
01082 }
01083
01084
01085 if ( ( vo = isAPropertyOf( vtodo, VCRelatedToProp ) ) != 0 ) {
01086 anEvent->setRelatedTo( s = fakeCString( vObjectUStringZValue( vo ) ) );
01087 deleteStr( s );
01088 d->mTodosRelate.append( anEvent );
01089 }
01090
01091
01092 Incidence::Secrecy secrecy = Incidence::SecrecyPublic;
01093 if ( ( vo = isAPropertyOf( vtodo, VCClassProp ) ) != 0 ) {
01094 s = fakeCString( vObjectUStringZValue( vo ) );
01095 if ( s && strcmp( s, "PRIVATE" ) == 0 ) {
01096 secrecy = Incidence::SecrecyPrivate;
01097 } else if ( s && strcmp( s, "CONFIDENTIAL" ) == 0 ) {
01098 secrecy = Incidence::SecrecyConfidential;
01099 }
01100 deleteStr( s );
01101 }
01102 anEvent->setSecrecy( secrecy );
01103
01104
01105 if ( ( vo = isAPropertyOf( vtodo, VCCategoriesProp ) ) != 0 ) {
01106 s = fakeCString( vObjectUStringZValue( vo ) );
01107 QString categories = QString::fromLocal8Bit( s );
01108 deleteStr( s );
01109 QStringList tmpStrList = categories.split( ';' );
01110 anEvent->setCategories( tmpStrList );
01111 }
01112
01113
01114 if ( ( vo = isAPropertyOf( vtodo, KPilotIdProp ) ) ) {
01115 anEvent->setNonKDECustomProperty(
01116 KPilotIdProp, QString::fromLocal8Bit( s = fakeCString( vObjectUStringZValue( vo ) ) ) );
01117 deleteStr( s );
01118 if ( ( vo = isAPropertyOf( vtodo, KPilotStatusProp ) ) ) {
01119 anEvent->setNonKDECustomProperty(
01120 KPilotStatusProp, QString::fromLocal8Bit( s = fakeCString( vObjectUStringZValue( vo ) ) ) );
01121 deleteStr( s );
01122 } else {
01123 anEvent->setNonKDECustomProperty( KPilotStatusProp, QString::number( int( SYNCMOD ) ) );
01124 }
01125 }
01126
01127 return anEvent;
01128 }
01129
01130 Event::Ptr VCalFormat::VEventToEvent( VObject *vevent )
01131 {
01132 VObject *vo;
01133 VObjectIterator voi;
01134 char *s;
01135
01136 Event::Ptr anEvent( new Event );
01137
01138
01139 if ( ( vo = isAPropertyOf( vevent, VCDCreatedProp ) ) != 0 ) {
01140 anEvent->setCreated( ISOToKDateTime( s = fakeCString( vObjectUStringZValue( vo ) ) ) );
01141 deleteStr( s );
01142 }
01143
01144
01145 vo = isAPropertyOf( vevent, VCUniqueStringProp );
01146
01147
01148 if ( vo ) {
01149 anEvent->setUid( s = fakeCString( vObjectUStringZValue( vo ) ) );
01150 deleteStr( s );
01151 }
01152
01153 #if defined(KCALCORE_FOR_SYMBIAN)
01154
01155 vo = isAPropertyOf( vevent, VCRecurrenceIdProp );
01156 if ( vo ) {
01157 anEvent->setRecurrenceId( ISOToKDateTime( s = fakeCString( vObjectUStringZValue( vo ) ) ) );
01158 deleteStr( s );
01159 }
01160 #endif
01161
01162
01163
01164 anEvent->setRevision( 0 );
01165 if ( ( vo = isAPropertyOf( vevent, VCSequenceProp ) ) != 0 ) {
01166 s = fakeCString( vObjectUStringZValue( vo ) );
01167 if ( s ) {
01168 anEvent->setRevision( atoi( s ) );
01169 deleteStr( s );
01170 }
01171 }
01172
01173
01174 if ( ( vo = isAPropertyOf( vevent, VCLastModifiedProp ) ) != 0 ) {
01175 anEvent->setLastModified( ISOToKDateTime( s = fakeCString( vObjectUStringZValue( vo ) ) ) );
01176 deleteStr( s );
01177 } else {
01178 anEvent->setLastModified( KDateTime::currentUtcDateTime() );
01179 }
01180
01181
01182
01183 if ( ( vo = isAPropertyOf( vevent, ICOrganizerProp ) ) != 0 ) {
01184
01185 anEvent->setOrganizer( s = fakeCString( vObjectUStringZValue( vo ) ) );
01186 deleteStr( s );
01187 } else {
01188 if ( d->mCalendar->owner()->name() != "Unknown Name" ) {
01189 anEvent->setOrganizer( d->mCalendar->owner() );
01190 }
01191 }
01192
01193
01194 initPropIterator( &voi, vevent );
01195 while ( moreIteration( &voi ) ) {
01196 vo = nextVObject( &voi );
01197 if ( strcmp( vObjectName( vo ), VCAttendeeProp ) == 0 ) {
01198 Attendee::Ptr a;
01199 VObject *vp;
01200 s = fakeCString( vObjectUStringZValue( vo ) );
01201 QString tmpStr = QString::fromLocal8Bit( s );
01202 deleteStr( s );
01203 tmpStr = tmpStr.simplified();
01204 int emailPos1, emailPos2;
01205 if ( ( emailPos1 = tmpStr.indexOf( '<' ) ) > 0 ) {
01206
01207 emailPos2 = tmpStr.lastIndexOf( '>' );
01208 a = Attendee::Ptr( new Attendee( tmpStr.left( emailPos1 - 1 ),
01209 tmpStr.mid( emailPos1 + 1,
01210 emailPos2 - ( emailPos1 + 1 ) ) ) );
01211 } else if ( tmpStr.indexOf( '@' ) > 0 ) {
01212
01213 a = Attendee::Ptr( new Attendee( 0, tmpStr ) );
01214 } else {
01215
01216 QString email = tmpStr.replace( ' ', '.' );
01217 a = Attendee::Ptr( new Attendee( tmpStr, email ) );
01218 }
01219
01220
01221 if ( ( vp = isAPropertyOf( vo, VCRSVPProp ) ) != 0 ) {
01222 a->setRSVP( vObjectStringZValue( vp ) );
01223 }
01224
01225 if ( ( vp = isAPropertyOf( vo, VCStatusProp ) ) != 0 ) {
01226 a->setStatus( readStatus( vObjectStringZValue( vp ) ) );
01227 }
01228
01229 anEvent->addAttendee( a );
01230 }
01231 }
01232
01233
01234
01235
01236
01237
01238
01239
01240
01241
01242 anEvent->setAllDay( false );
01243
01244
01245 if ( ( vo = isAPropertyOf( vevent, VCDTstartProp ) ) != 0 ) {
01246 anEvent->setDtStart( ISOToKDateTime( s = fakeCString( vObjectUStringZValue( vo ) ) ) );
01247 deleteStr( s );
01248
01249 if ( anEvent->dtStart().time().hour() == 0 &&
01250 anEvent->dtStart().time().minute() == 0 &&
01251 anEvent->dtStart().time().second() == 0 ) {
01252 anEvent->setAllDay( true );
01253 }
01254 }
01255
01256
01257 if ( ( vo = isAPropertyOf( vevent, VCDTendProp ) ) != 0 ) {
01258 anEvent->setDtEnd( ISOToKDateTime( s = fakeCString( vObjectUStringZValue( vo ) ) ) );
01259 deleteStr( s );
01260
01261 if ( anEvent->dtEnd().time().hour() == 0 &&
01262 anEvent->dtEnd().time().minute() == 0 &&
01263 anEvent->dtEnd().time().second() == 0 ) {
01264 anEvent->setAllDay( true );
01265 }
01266 }
01267 #if defined(KCALCORE_FOR_MEEGO)
01268 if ( anEvent->allDay() ) {
01269 if ( anEvent->dtEnd() == anEvent->dtStart() ) {
01270 anEvent->setDtEnd( anEvent->dtEnd().addDays( 1 ) );
01271 }
01272 }
01273 #endif
01274
01275
01276
01277 if ( !isAPropertyOf( vevent, VCDTstartProp ) ) {
01278 anEvent->setDtStart( anEvent->dtEnd() );
01279 }
01280 if ( ! isAPropertyOf( vevent, VCDTendProp ) ) {
01281 anEvent->setDtEnd( anEvent->dtStart() );
01282 }
01283
01285
01286
01287 if ( ( vo = isAPropertyOf( vevent, VCRRuleProp ) ) != 0 ) {
01288 QString tmpStr = ( s = fakeCString( vObjectUStringZValue( vo ) ) );
01289 deleteStr( s );
01290 tmpStr.simplified();
01291 tmpStr = tmpStr.toUpper();
01292
01293 int typelen = 1;
01294 uint type = Recurrence::rNone;
01295 if ( tmpStr.left(1) == "D" ) {
01296 type = Recurrence::rDaily;
01297 } else if ( tmpStr.left(1) == "W" ) {
01298 type = Recurrence::rWeekly;
01299 } else {
01300 typelen = 2;
01301 if ( tmpStr.left(2) == "MP" ) {
01302 type = Recurrence::rMonthlyPos;
01303 } else if ( tmpStr.left(2) == "MD" ) {
01304 type = Recurrence::rMonthlyDay;
01305 } else if ( tmpStr.left(2) == "YM" ) {
01306 type = Recurrence::rYearlyMonth;
01307 } else if ( tmpStr.left(2) == "YD" ) {
01308 type = Recurrence::rYearlyDay;
01309 }
01310 }
01311
01312 if ( type != Recurrence::rNone ) {
01313
01314
01315 int index = tmpStr.indexOf( ' ' );
01316 int last = tmpStr.lastIndexOf( ' ' ) + 1;
01317 int rFreq = tmpStr.mid( typelen, ( index - 1 ) ).toInt();
01318 ++index;
01319
01320
01321 switch ( type ) {
01322 case Recurrence::rDaily:
01323 anEvent->recurrence()->setDaily(rFreq);
01324 break;
01325
01326 case Recurrence::rWeekly:
01327 {
01328 QBitArray qba(7);
01329 QString dayStr;
01330 if ( index == last ) {
01331
01332 qba.setBit( anEvent->dtStart().date().dayOfWeek() - 1 );
01333 } else {
01334
01335 while ( index < last ) {
01336 dayStr = tmpStr.mid( index, 3 );
01337 int dayNum = numFromDay( dayStr );
01338 if ( dayNum >= 0 ) {
01339 qba.setBit( dayNum );
01340 }
01341 index += 3;
01342 }
01343 }
01344 anEvent->recurrence()->setWeekly( rFreq, qba );
01345 break;
01346 }
01347
01348 case Recurrence::rMonthlyPos:
01349 {
01350 anEvent->recurrence()->setMonthly( rFreq );
01351
01352 QBitArray qba(7);
01353 short tmpPos;
01354 if ( index == last ) {
01355
01356 tmpPos = anEvent->dtStart().date().day() / 7 + 1;
01357 if ( tmpPos == 5 ) {
01358 tmpPos = -1;
01359 }
01360 qba.setBit( anEvent->dtStart().date().dayOfWeek() - 1 );
01361 anEvent->recurrence()->addMonthlyPos( tmpPos, qba );
01362 } else {
01363
01364 while ( index < last ) {
01365 tmpPos = tmpStr.mid( index, 1 ).toShort();
01366 index += 1;
01367 if ( tmpStr.mid( index, 1 ) == "-" ) {
01368
01369 tmpPos = 0 - tmpPos;
01370 }
01371 index += 2;
01372 while ( numFromDay( tmpStr.mid( index, 3 ) ) >= 0 ) {
01373 int dayNum = numFromDay( tmpStr.mid( index, 3 ) );
01374 qba.setBit( dayNum );
01375 index += 3;
01376 }
01377 anEvent->recurrence()->addMonthlyPos( tmpPos, qba );
01378 qba.detach();
01379 qba.fill( false );
01380 }
01381 }
01382 break;
01383 }
01384
01385 case Recurrence::rMonthlyDay:
01386 anEvent->recurrence()->setMonthly( rFreq );
01387 if( index == last ) {
01388
01389 short tmpDay = anEvent->dtStart().date().day();
01390 anEvent->recurrence()->addMonthlyDate( tmpDay );
01391 } else {
01392
01393 while ( index < last ) {
01394 int index2 = tmpStr.indexOf( ' ', index );
01395 if ( ( tmpStr.mid( ( index2 - 1 ), 1 ) == "-" ) ||
01396 ( tmpStr.mid( ( index2 - 1 ), 1 ) == "+" ) ) {
01397 index2 = index2 - 1;
01398 }
01399 short tmpDay = tmpStr.mid( index, ( index2 - index ) ).toShort();
01400 index = index2;
01401 if ( tmpStr.mid( index, 1 ) == "-" ) {
01402 tmpDay = 0 - tmpDay;
01403 }
01404 index += 2;
01405 anEvent->recurrence()->addMonthlyDate( tmpDay );
01406 }
01407 }
01408 break;
01409
01410 case Recurrence::rYearlyMonth:
01411 anEvent->recurrence()->setYearly( rFreq );
01412
01413 if ( index == last ) {
01414
01415 short tmpMonth = anEvent->dtStart().date().month();
01416 anEvent->recurrence()->addYearlyMonth( tmpMonth );
01417 } else {
01418
01419 while ( index < last ) {
01420 int index2 = tmpStr.indexOf( ' ', index );
01421 short tmpMonth = tmpStr.mid( index, ( index2 - index ) ).toShort();
01422 index = index2 + 1;
01423 anEvent->recurrence()->addYearlyMonth( tmpMonth );
01424 }
01425 }
01426 break;
01427
01428 case Recurrence::rYearlyDay:
01429 anEvent->recurrence()->setYearly( rFreq );
01430
01431 if ( index == last ) {
01432
01433 short tmpDay = anEvent->dtStart().date().dayOfYear();
01434 anEvent->recurrence()->addYearlyDay( tmpDay );
01435 } else {
01436
01437 while ( index < last ) {
01438 int index2 = tmpStr.indexOf( ' ', index );
01439 short tmpDay = tmpStr.mid( index, ( index2 - index ) ).toShort();
01440 index = index2 + 1;
01441 anEvent->recurrence()->addYearlyDay( tmpDay );
01442 }
01443 }
01444 break;
01445
01446 default:
01447 break;
01448 }
01449
01450
01451 index = last;
01452 if ( tmpStr.mid( index, 1 ) == "#" ) {
01453
01454 index++;
01455 int rDuration = tmpStr.mid( index, tmpStr.length() - index ).toInt();
01456 if ( rDuration > 0 ) {
01457 anEvent->recurrence()->setDuration( rDuration );
01458 }
01459 } else if ( tmpStr.indexOf( 'T', index ) != -1 ) {
01460 KDateTime rEndDate = ISOToKDateTime( tmpStr.mid( index, tmpStr.length() - index ) );
01461 anEvent->recurrence()->setEndDateTime( rEndDate );
01462 }
01463
01464
01465 } else {
01466 kDebug() << "we don't understand this type of recurrence!";
01467 }
01468 }
01469
01470
01471 if ( ( vo = isAPropertyOf( vevent, VCExpDateProp ) ) != 0 ) {
01472 s = fakeCString( vObjectUStringZValue( vo ) );
01473 QStringList exDates = QString::fromLocal8Bit( s ).split( ',' );
01474 QStringList::ConstIterator it;
01475 for ( it = exDates.constBegin(); it != exDates.constEnd(); ++it ) {
01476 KDateTime exDate = ISOToKDateTime(*it);
01477 if ( exDate.time().hour() == 0 &&
01478 exDate.time().minute() == 0 &&
01479 exDate.time().second() == 0 ) {
01480 anEvent->recurrence()->addExDate( ISOToQDate( *it ) );
01481 } else {
01482 anEvent->recurrence()->addExDateTime( exDate );
01483 }
01484 }
01485 deleteStr( s );
01486 }
01487
01488
01489 if ( ( vo = isAPropertyOf( vevent, VCSummaryProp ) ) ) {
01490 s = fakeCString( vObjectUStringZValue( vo ) );
01491 anEvent->setSummary( QString::fromLocal8Bit( s ), Qt::mightBeRichText( s ) );
01492 deleteStr( s );
01493 }
01494
01495
01496 if ( ( vo = isAPropertyOf( vevent, VCDescriptionProp ) ) != 0 ) {
01497 s = fakeCString( vObjectUStringZValue( vo ) );
01498 bool isRich = Qt::mightBeRichText( s );
01499 if ( !anEvent->description().isEmpty() ) {
01500 anEvent->setDescription(
01501 anEvent->description() + '\n' + QString::fromLocal8Bit( s ), isRich );
01502 } else {
01503 anEvent->setDescription( QString::fromLocal8Bit( s ), isRich );
01504 }
01505 deleteStr( s );
01506 }
01507
01508
01509 if ( ( vo = isAPropertyOf( vevent, VCLocationProp ) ) != 0 ) {
01510 s = fakeCString( vObjectUStringZValue( vo ) );
01511 anEvent->setLocation( QString::fromLocal8Bit( s ), Qt::mightBeRichText( s ) );
01512 deleteStr( s );
01513 }
01514
01515
01516
01517 if ( anEvent->summary().isEmpty() && !( anEvent->description().isEmpty() ) ) {
01518 QString tmpStr = anEvent->description().simplified();
01519 anEvent->setDescription( "" );
01520 anEvent->setSummary( tmpStr );
01521 }
01522
01523 #if 0
01524
01525 if ( ( vo = isAPropertyOf( vevent, VCStatusProp ) ) != 0 ) {
01526 QString tmpStr( s = fakeCString( vObjectUStringZValue( vo ) ) );
01527 deleteStr( s );
01528
01529
01530 } else {
01531
01532 }
01533 #endif
01534
01535
01536 Incidence::Secrecy secrecy = Incidence::SecrecyPublic;
01537 if ( ( vo = isAPropertyOf( vevent, VCClassProp ) ) != 0 ) {
01538 s = fakeCString( vObjectUStringZValue( vo ) );
01539 if ( s && strcmp( s, "PRIVATE" ) == 0 ) {
01540 secrecy = Incidence::SecrecyPrivate;
01541 } else if ( s && strcmp( s, "CONFIDENTIAL" ) == 0 ) {
01542 secrecy = Incidence::SecrecyConfidential;
01543 }
01544 deleteStr( s );
01545 }
01546 anEvent->setSecrecy( secrecy );
01547
01548
01549 if ( ( vo = isAPropertyOf( vevent, VCCategoriesProp ) ) != 0 ) {
01550 s = fakeCString( vObjectUStringZValue( vo ) );
01551 QString categories = QString::fromLocal8Bit( s );
01552 deleteStr( s );
01553 QStringList tmpStrList = categories.split( ',' );
01554 anEvent->setCategories( tmpStrList );
01555 }
01556
01557
01558 initPropIterator( &voi, vevent );
01559 while ( moreIteration( &voi ) ) {
01560 vo = nextVObject( &voi );
01561 if ( strcmp( vObjectName( vo ), VCAttachProp ) == 0 ) {
01562 s = fakeCString( vObjectUStringZValue( vo ) );
01563 anEvent->addAttachment( Attachment::Ptr( new Attachment( QString( s ) ) ) );
01564 deleteStr( s );
01565 }
01566 }
01567
01568
01569 if ( ( vo = isAPropertyOf( vevent, VCResourcesProp ) ) != 0 ) {
01570 QString resources = ( s = fakeCString( vObjectUStringZValue( vo ) ) );
01571 deleteStr( s );
01572 QStringList tmpStrList = resources.split( ';' );
01573 anEvent->setResources( tmpStrList );
01574 }
01575
01576
01577 if ( ( vo = isAPropertyOf( vevent, VCDAlarmProp ) ) ) {
01578 Alarm::Ptr alarm;
01579 VObject *a;
01580 VObject *b;
01581 a = isAPropertyOf( vo, VCRunTimeProp );
01582 b = isAPropertyOf( vo, VCDisplayStringProp );
01583
01584 if ( a || b ) {
01585 alarm = anEvent->newAlarm();
01586 if ( a ) {
01587 alarm->setTime( ISOToKDateTime( s = fakeCString( vObjectUStringZValue( a ) ) ) );
01588 deleteStr( s );
01589 }
01590 alarm->setEnabled( true );
01591
01592 if ( b ) {
01593 s = fakeCString( vObjectUStringZValue( b ) );
01594 alarm->setDisplayAlarm( QString( s ) );
01595 deleteStr( s );
01596 } else {
01597 alarm->setDisplayAlarm( QString() );
01598 }
01599 }
01600 }
01601
01602 if ( ( vo = isAPropertyOf( vevent, VCAAlarmProp ) ) ) {
01603 Alarm::Ptr alarm;
01604 VObject *a;
01605 VObject *b;
01606 a = isAPropertyOf( vo, VCRunTimeProp );
01607 b = isAPropertyOf( vo, VCAudioContentProp );
01608
01609 if ( a || b ) {
01610 alarm = anEvent->newAlarm();
01611 if ( a ) {
01612 alarm->setTime( ISOToKDateTime( s = fakeCString( vObjectUStringZValue( a ) ) ) );
01613 deleteStr( s );
01614 }
01615 alarm->setEnabled( true );
01616
01617 if ( b ) {
01618 s = fakeCString( vObjectUStringZValue( b ) );
01619 alarm->setAudioAlarm( QFile::decodeName( s ) );
01620 deleteStr( s );
01621 } else {
01622 alarm->setAudioAlarm( QString() );
01623 }
01624 }
01625 }
01626
01627 if ( ( vo = isAPropertyOf( vevent, VCPAlarmProp ) ) ) {
01628 Alarm::Ptr alarm;
01629 VObject *a;
01630 VObject *b;
01631 a = isAPropertyOf( vo, VCRunTimeProp );
01632 b = isAPropertyOf( vo, VCProcedureNameProp );
01633
01634 if ( a || b ) {
01635 alarm = anEvent->newAlarm();
01636 if ( a ) {
01637 alarm->setTime( ISOToKDateTime( s = fakeCString( vObjectUStringZValue( a ) ) ) );
01638 deleteStr( s );
01639 }
01640 alarm->setEnabled( true );
01641
01642 if ( b ) {
01643 s = fakeCString( vObjectUStringZValue( b ) );
01644 alarm->setProcedureAlarm( QFile::decodeName( s ) );
01645 deleteStr( s );
01646 } else {
01647 alarm->setProcedureAlarm( QString() );
01648 }
01649 }
01650 }
01651
01652
01653 if ( ( vo = isAPropertyOf( vevent, VCPriorityProp ) ) ) {
01654 s = fakeCString( vObjectUStringZValue( vo ) );
01655 if ( s ) {
01656 anEvent->setPriority( atoi( s ) );
01657 deleteStr( s );
01658 }
01659 }
01660
01661
01662 if ( ( vo = isAPropertyOf( vevent, VCTranspProp ) ) != 0 ) {
01663 s = fakeCString( vObjectUStringZValue( vo ) );
01664 if ( s ) {
01665 int i = atoi( s );
01666 anEvent->setTransparency( i == 1 ? Event::Transparent : Event::Opaque );
01667 deleteStr( s );
01668 }
01669 }
01670
01671
01672 if ( ( vo = isAPropertyOf( vevent, VCRelatedToProp ) ) != 0 ) {
01673 anEvent->setRelatedTo( s = fakeCString( vObjectUStringZValue( vo ) ) );
01674 deleteStr( s );
01675 d->mEventsRelate.append( anEvent );
01676 }
01677
01678
01679 if ( ( vo = isAPropertyOf( vevent, KPilotIdProp ) ) ) {
01680 anEvent->setNonKDECustomProperty(
01681 KPilotIdProp, QString::fromLocal8Bit( s = fakeCString( vObjectUStringZValue( vo ) ) ) );
01682 deleteStr( s );
01683 if ( ( vo = isAPropertyOf( vevent, KPilotStatusProp ) ) ) {
01684 anEvent->setNonKDECustomProperty(
01685 KPilotStatusProp, QString::fromLocal8Bit( s = fakeCString( vObjectUStringZValue( vo ) ) ) );
01686 deleteStr( s );
01687 } else {
01688 anEvent->setNonKDECustomProperty( KPilotStatusProp, QString::number( int( SYNCMOD ) ) );
01689 }
01690 }
01691
01692
01693 readCustomProperties( vevent, anEvent );
01694
01695 return anEvent;
01696 }
01697
01698 QString VCalFormat::parseTZ( const QByteArray &timezone ) const
01699 {
01700 QString pZone = timezone.mid( timezone.indexOf( "TZID:VCAL" ) + 9 );
01701 return pZone.mid( 0, pZone.indexOf(QChar( QLatin1Char( '\n' ) ) ) );
01702 }
01703
01704 QString VCalFormat::parseDst( QByteArray &timezone ) const
01705 {
01706 if ( !timezone.contains( "BEGIN:DAYLIGHT" ) ) {
01707 return QString();
01708 }
01709
01710 timezone = timezone.mid( timezone.indexOf( "BEGIN:DAYLIGHT" ) );
01711 timezone = timezone.mid( timezone.indexOf( "TZNAME:" ) + 7 );
01712 QString sStart = timezone.mid( 0, ( timezone.indexOf( "COMMENT:" ) ) );
01713 sStart.chop( 2 );
01714 timezone = timezone.mid( timezone.indexOf( "TZOFFSETTO:" ) + 11 );
01715 QString sOffset = timezone.mid( 0, ( timezone.indexOf( "DTSTART:" ) ) );
01716 sOffset.chop( 2 );
01717 sOffset.insert( 3, QString( ":" ) );
01718 timezone = timezone.mid( timezone.indexOf( "TZNAME:" ) + 7 );
01719 QString sEnd = timezone.mid( 0, ( timezone.indexOf( "COMMENT:" ) ) );
01720 sEnd.chop( 2 );
01721
01722 return "TRUE;" + sOffset + ';' + sStart + ';' + sEnd + ";;";
01723 }
01724
01725 QString VCalFormat::qDateToISO( const QDate &qd )
01726 {
01727 QString tmpStr;
01728
01729 if ( !qd.isValid() ) {
01730 return QString();
01731 }
01732
01733 tmpStr.sprintf( "%.2d%.2d%.2d", qd.year(), qd.month(), qd.day() );
01734 return tmpStr;
01735
01736 }
01737
01738 QString VCalFormat::kDateTimeToISO( const KDateTime &dt, bool zulu )
01739 {
01740 QString tmpStr;
01741
01742 if ( !dt.isValid() ) {
01743 return QString();
01744 }
01745
01746 QDateTime tmpDT;
01747 if ( zulu ) {
01748 tmpDT = dt.toUtc().dateTime();
01749 } else {
01750 #if !defined(KCALCORE_FOR_MEEGO)
01751 tmpDT = dt.toTimeSpec( d->mCalendar->timeSpec() ).dateTime();
01752 #else
01753 tmpDT = dt.dateTime();
01754 #endif
01755 }
01756 tmpStr.sprintf( "%.2d%.2d%.2dT%.2d%.2d%.2d",
01757 tmpDT.date().year(), tmpDT.date().month(),
01758 tmpDT.date().day(), tmpDT.time().hour(),
01759 tmpDT.time().minute(), tmpDT.time().second() );
01760 if ( zulu || dt.isUtc() ) {
01761 tmpStr += 'Z';
01762 }
01763 return tmpStr;
01764 }
01765
01766 KDateTime VCalFormat::ISOToKDateTime( const QString &dtStr )
01767 {
01768 QDate tmpDate;
01769 QTime tmpTime;
01770 QString tmpStr;
01771 int year, month, day, hour, minute, second;
01772
01773 tmpStr = dtStr;
01774 year = tmpStr.left( 4 ).toInt();
01775 month = tmpStr.mid( 4, 2 ).toInt();
01776 day = tmpStr.mid( 6, 2 ).toInt();
01777 hour = tmpStr.mid( 9, 2 ).toInt();
01778 minute = tmpStr.mid( 11, 2 ).toInt();
01779 second = tmpStr.mid( 13, 2 ).toInt();
01780 tmpDate.setYMD( year, month, day );
01781 tmpTime.setHMS( hour, minute, second );
01782
01783 if ( tmpDate.isValid() && tmpTime.isValid() ) {
01784
01785 if ( dtStr.at( dtStr.length() - 1 ) == 'Z' ) {
01786 return KDateTime( tmpDate, tmpTime, KDateTime::UTC );
01787 } else {
01788 return KDateTime( tmpDate, tmpTime, d->mCalendar->timeSpec() );
01789 }
01790 } else {
01791 return KDateTime();
01792 }
01793 }
01794
01795 QDate VCalFormat::ISOToQDate( const QString &dateStr )
01796 {
01797 int year, month, day;
01798
01799 year = dateStr.left( 4 ).toInt();
01800 month = dateStr.mid( 4, 2 ).toInt();
01801 day = dateStr.mid( 6, 2 ).toInt();
01802
01803 return QDate( year, month, day );
01804 }
01805
01806 bool VCalFormat::parseTZOffsetISO8601( const QString &s, int &result )
01807 {
01808
01809
01810
01811
01812
01813
01814 int mod = 1;
01815 int v = 0;
01816 QString str = s.trimmed();
01817 int ofs = 0;
01818 result = 0;
01819
01820
01821 if ( str.size() <= ofs ) {
01822 return false;
01823 }
01824 if ( str[ofs] == '-' ) {
01825 mod = -1;
01826 ofs++;
01827 } else if ( str[ofs] == '+' ) {
01828 ofs++;
01829 }
01830 if ( str.size() <= ofs ) {
01831 return false;
01832 }
01833
01834
01835 bool ok;
01836
01837 if ( str.size() < ( ofs + 2 ) ) {
01838 return false;
01839 }
01840
01841 v = str.mid( ofs, 2 ).toInt( &ok ) * 60;
01842 if ( !ok ) {
01843 return false;
01844 }
01845 ofs += 2;
01846
01847 if ( str.size() > ofs ) {
01848 if ( str[ofs] == ':' ) {
01849 ofs++;
01850 }
01851 if ( str.size() > ofs ) {
01852 if ( str.size() < ( ofs + 2 ) ) {
01853 return false;
01854 }
01855 v += str.mid( ofs, 2 ).toInt( &ok );
01856 if ( !ok ) {
01857 return false;
01858 }
01859 }
01860 }
01861 result = v * mod * 60;
01862 return true;
01863 }
01864
01865
01866
01867
01868 void VCalFormat::populate( VObject *vcal, bool deleted, const QString ¬ebook )
01869 {
01870 Q_UNUSED( notebook );
01871
01872
01873
01874 VObjectIterator i;
01875 VObject *curVO, *curVOProp;
01876 Event::Ptr anEvent;
01877 bool hasTimeZone = false;
01878 KDateTime::Spec previousSpec;
01879
01880 if ( ( curVO = isAPropertyOf( vcal, ICMethodProp ) ) != 0 ) {
01881 char *methodType = 0;
01882 methodType = fakeCString( vObjectUStringZValue( curVO ) );
01883 kDebug() << "This calendar is an iTIP transaction of type '"
01884 << methodType << "'";
01885 deleteStr( methodType );
01886 }
01887
01888
01889 if ( ( curVO = isAPropertyOf( vcal, VCProdIdProp ) ) != 0 ) {
01890 char *s = fakeCString( vObjectUStringZValue( curVO ) );
01891 if ( !s || strcmp( productId().toLocal8Bit(), s ) != 0 ) {
01892 kDebug() << "This vCalendar file was not created by KOrganizer or"
01893 << "any other product we support. Loading anyway...";
01894 }
01895 setLoadedProductId( s );
01896 deleteStr( s );
01897 }
01898
01899
01900 if ( ( curVO = isAPropertyOf( vcal, VCVersionProp ) ) != 0 ) {
01901 char *s = fakeCString( vObjectUStringZValue( curVO ) );
01902 if ( !s || strcmp( _VCAL_VERSION, s ) != 0 ) {
01903 kDebug() << "This vCalendar file has version" << s
01904 << "We only support" << _VCAL_VERSION;
01905 }
01906 deleteStr( s );
01907 }
01908
01909
01910 if ( ( curVO = isAPropertyOf( vcal, VCTimeZoneProp ) ) != 0 ) {
01911 char *s = fakeCString( vObjectUStringZValue( curVO ) );
01912 QString ts( s );
01913 QString name = "VCAL" + ts;
01914 deleteStr( s );
01915
01916
01917
01918
01919
01920
01921 QStringList tzList;
01922 QString tz;
01923 int utcOffset;
01924 int utcOffsetDst;
01925 if ( parseTZOffsetISO8601( ts, utcOffset ) ) {
01926 kDebug() << "got standard offset" << ts << utcOffset;
01927
01928
01929 KDateTime dt = KDateTime( QDateTime( QDate( 1900, 1, 1 ), QTime( 0, 0, 0 ) ) );
01930 tz = QString( "STD;%1;false;%2" ).arg( QString::number( utcOffset ) ).arg( dt.toString() );
01931 tzList.append( tz );
01932
01933
01934 initPropIterator( &i, vcal );
01935 while ( moreIteration( &i ) ) {
01936 curVO = nextVObject( &i );
01937 if ( strcmp( vObjectName( curVO ), VCDayLightProp ) == 0 ) {
01938 char *s = fakeCString( vObjectUStringZValue( curVO ) );
01939 QString dst = QString( s );
01940 QStringList argl = dst.split( ',' );
01941 deleteStr( s );
01942
01943
01944 if ( argl.size() < 4 ) {
01945 continue;
01946 }
01947
01948
01949 if ( argl[0] != "TRUE" ) {
01950 continue;
01951 }
01952
01953 if ( parseTZOffsetISO8601( argl[1], utcOffsetDst ) ) {
01954
01955 kDebug() << "got DST offset" << argl[1] << utcOffsetDst;
01956
01957 QString strDate = argl[3];
01958 KDateTime endDate = ISOToKDateTime( strDate );
01959 tz = QString( "%1;%2;false;%3" ).
01960 arg( strDate ).
01961 arg( QString::number( utcOffset ) ).
01962 arg( endDate.toString() );
01963 tzList.append( tz );
01964
01965
01966 strDate = argl[2];
01967 KDateTime startDate = ISOToKDateTime( strDate );
01968 tz = QString( "%1;%2;true;%3" ).
01969 arg( strDate ).
01970 arg( QString::number( utcOffsetDst ) ).
01971 arg( startDate.toString() );
01972 tzList.append( tz );
01973 } else {
01974 kDebug() << "unable to parse dst" << argl[1];
01975 }
01976 }
01977 }
01978 ICalTimeZones *tzlist = d->mCalendar->timeZones();
01979 ICalTimeZoneSource tzs;
01980 ICalTimeZone zone = tzs.parse( name, tzList, *tzlist );
01981 if ( !zone.isValid() ) {
01982 kDebug() << "zone is not valid, parsing error" << tzList;
01983 } else {
01984 previousSpec = d->mCalendar->timeSpec();
01985 d->mCalendar->setTimeZoneId( name );
01986 hasTimeZone = true;
01987 }
01988 } else {
01989 kDebug() << "unable to parse tzoffset" << ts;
01990 }
01991 }
01992
01993
01994 d->mEventsRelate.clear();
01995 d->mTodosRelate.clear();
01996
01997 initPropIterator( &i, vcal );
01998
01999
02000 while ( moreIteration( &i ) ) {
02001 curVO = nextVObject( &i );
02002
02003
02004
02005
02006 if ( strcmp( vObjectName( curVO ), VCEventProp ) == 0 ) {
02007
02008 if ( ( curVOProp = isAPropertyOf( curVO, KPilotStatusProp ) ) != 0 ) {
02009 char *s;
02010 s = fakeCString( vObjectUStringZValue( curVOProp ) );
02011
02012 if ( s ) {
02013 if ( atoi( s ) == SYNCDEL ) {
02014 deleteStr( s );
02015 kDebug() << "skipping pilot-deleted event";
02016 goto SKIP;
02017 }
02018 deleteStr( s );
02019 }
02020 }
02021
02022 if ( !isAPropertyOf( curVO, VCDTstartProp ) &&
02023 !isAPropertyOf( curVO, VCDTendProp ) ) {
02024 kDebug() << "found a VEvent with no DTSTART and no DTEND! Skipping...";
02025 goto SKIP;
02026 }
02027
02028 anEvent = VEventToEvent( curVO );
02029 if ( anEvent ) {
02030 if ( hasTimeZone && !anEvent->allDay() && anEvent->dtStart().isUtc() ) {
02031
02032
02033
02034
02035 int utcOffSet = anEvent->dtStart().utcOffset();
02036 KDateTime dtStart( anEvent->dtStart().dateTime().addSecs( utcOffSet ),
02037 d->mCalendar->timeSpec() );
02038 KDateTime dtEnd( anEvent->dtEnd().dateTime().addSecs( utcOffSet ),
02039 d->mCalendar->timeSpec() );
02040 anEvent->setDtStart( dtStart );
02041 anEvent->setDtEnd( dtEnd );
02042 }
02043 Event::Ptr old = !anEvent->hasRecurrenceId() ?
02044 d->mCalendar->event( anEvent->uid() ) :
02045 d->mCalendar->event( anEvent->uid(), anEvent->recurrenceId() );
02046
02047 if ( old ) {
02048 if ( deleted ) {
02049 d->mCalendar->deleteEvent( old );
02050 removeAllVCal( d->mEventsRelate, old );
02051 } else if ( anEvent->revision() > old->revision() ) {
02052 d->mCalendar->deleteEvent( old );
02053 removeAllVCal( d->mEventsRelate, old );
02054 d->mCalendar->addEvent( anEvent );
02055 }
02056 } else if ( deleted ) {
02057 old = !anEvent->hasRecurrenceId() ?
02058 d->mCalendar->deletedEvent( anEvent->uid() ) :
02059 d->mCalendar->deletedEvent( anEvent->uid(), anEvent->recurrenceId() );
02060 if ( !old ) {
02061 d->mCalendar->addEvent( anEvent );
02062 d->mCalendar->deleteEvent( anEvent );
02063 }
02064 } else {
02065 d->mCalendar->addEvent( anEvent );
02066 }
02067 }
02068 } else if ( strcmp( vObjectName( curVO ), VCTodoProp ) == 0 ) {
02069 Todo::Ptr aTodo = VTodoToEvent( curVO );
02070 if ( aTodo ) {
02071 if ( hasTimeZone && !aTodo->allDay() && aTodo->dtStart().isUtc() ) {
02072
02073
02074
02075
02076 int utcOffSet = aTodo->dtStart().utcOffset();
02077 KDateTime dtStart( aTodo->dtStart().dateTime().addSecs( utcOffSet ),
02078 d->mCalendar->timeSpec() );
02079 aTodo->setDtStart( dtStart );
02080 if ( aTodo->hasDueDate() ) {
02081 KDateTime dtDue( aTodo->dtDue().dateTime().addSecs( utcOffSet ),
02082 d->mCalendar->timeSpec() );
02083 aTodo->setDtDue( dtDue );
02084 }
02085 }
02086 Todo::Ptr old = !aTodo->hasRecurrenceId() ?
02087 d->mCalendar->todo( aTodo->uid() ) :
02088 d->mCalendar->todo( aTodo->uid(), aTodo->recurrenceId() );
02089 if ( old ) {
02090 if ( deleted ) {
02091 d->mCalendar->deleteTodo( old );
02092 removeAllVCal( d->mTodosRelate, old );
02093 } else if ( aTodo->revision() > old->revision() ) {
02094 d->mCalendar->deleteTodo( old );
02095 removeAllVCal( d->mTodosRelate, old );
02096 d->mCalendar->addTodo( aTodo );
02097 }
02098 } else if ( deleted ) {
02099 old = d->mCalendar->deletedTodo( aTodo->uid(), aTodo->recurrenceId() );
02100 if ( !old ) {
02101 d->mCalendar->addTodo( aTodo );
02102 d->mCalendar->deleteTodo( aTodo );
02103 }
02104 } else {
02105 d->mCalendar->addTodo( aTodo );
02106 }
02107 }
02108 } else if ( ( strcmp( vObjectName( curVO ), VCVersionProp ) == 0 ) ||
02109 ( strcmp( vObjectName( curVO ), VCProdIdProp ) == 0 ) ||
02110 ( strcmp( vObjectName( curVO ), VCTimeZoneProp ) == 0 ) ) {
02111
02112
02113 ;
02114 } else if ( strcmp( vObjectName( curVO ), VCDayLightProp ) == 0 ) {
02115
02116 ;
02117 } else {
02118 kDebug() << "Ignoring unknown vObject \"" << vObjectName(curVO) << "\"";
02119 }
02120 SKIP:
02121 ;
02122 }
02123
02124
02125 Event::List::ConstIterator eIt;
02126 for ( eIt = d->mEventsRelate.constBegin(); eIt != d->mEventsRelate.constEnd(); ++eIt ) {
02127 (*eIt)->setRelatedTo( (*eIt)->relatedTo() );
02128 }
02129 Todo::List::ConstIterator tIt;
02130 for ( tIt = d->mTodosRelate.constBegin(); tIt != d->mTodosRelate.constEnd(); ++tIt ) {
02131 (*tIt)->setRelatedTo( (*tIt)->relatedTo() );
02132 }
02133
02134
02135 if ( hasTimeZone ) {
02136 d->mCalendar->setTimeSpec(previousSpec);
02137 }
02138
02139 }
02140
02141 const char *VCalFormat::dayFromNum( int day )
02142 {
02143 const char *days[7] = { "MO ", "TU ", "WE ", "TH ", "FR ", "SA ", "SU " };
02144
02145 return days[day];
02146 }
02147
02148 int VCalFormat::numFromDay( const QString &day )
02149 {
02150 if ( day == "MO " ) {
02151 return 0;
02152 }
02153 if ( day == "TU " ) {
02154 return 1;
02155 }
02156 if ( day == "WE " ) {
02157 return 2;
02158 }
02159 if ( day == "TH " ) {
02160 return 3;
02161 }
02162 if ( day == "FR " ) {
02163 return 4;
02164 }
02165 if ( day == "SA " ) {
02166 return 5;
02167 }
02168 if ( day == "SU " ) {
02169 return 6;
02170 }
02171
02172 return -1;
02173 }
02174
02175 Attendee::PartStat VCalFormat::readStatus( const char *s ) const
02176 {
02177 QString statStr = s;
02178 statStr = statStr.toUpper();
02179 Attendee::PartStat status;
02180
02181 if ( statStr == "X-ACTION" ) {
02182 status = Attendee::NeedsAction;
02183 } else if ( statStr == "NEEDS ACTION" ) {
02184 status = Attendee::NeedsAction;
02185 } else if ( statStr == "ACCEPTED" ) {
02186 status = Attendee::Accepted;
02187 } else if ( statStr == "SENT" ) {
02188 status = Attendee::NeedsAction;
02189 } else if ( statStr == "TENTATIVE" ) {
02190 status = Attendee::Tentative;
02191 } else if ( statStr == "CONFIRMED" ) {
02192 status = Attendee::Accepted;
02193 } else if ( statStr == "DECLINED" ) {
02194 status = Attendee::Declined;
02195 } else if ( statStr == "COMPLETED" ) {
02196 status = Attendee::Completed;
02197 } else if ( statStr == "DELEGATED" ) {
02198 status = Attendee::Delegated;
02199 } else {
02200 kDebug() << "error setting attendee mStatus, unknown mStatus!";
02201 status = Attendee::NeedsAction;
02202 }
02203
02204 return status;
02205 }
02206
02207 QByteArray VCalFormat::writeStatus( Attendee::PartStat status ) const
02208 {
02209 switch( status ) {
02210 default:
02211 case Attendee::NeedsAction:
02212 return "NEEDS ACTION";
02213 break;
02214 case Attendee::Accepted:
02215 return "ACCEPTED";
02216 break;
02217 case Attendee::Declined:
02218 return "DECLINED";
02219 break;
02220 case Attendee::Tentative:
02221 return "TENTATIVE";
02222 break;
02223 case Attendee::Delegated:
02224 return "DELEGATED";
02225 break;
02226 case Attendee::Completed:
02227 return "COMPLETED";
02228 break;
02229 case Attendee::InProcess:
02230 return "NEEDS ACTION";
02231 break;
02232 }
02233 }
02234
02235 void VCalFormat::readCustomProperties( VObject *o, const Incidence::Ptr &i )
02236 {
02237 VObjectIterator iter;
02238 VObject *cur;
02239 const char *curname;
02240 char *s;
02241
02242 initPropIterator( &iter, o );
02243 while ( moreIteration( &iter ) ) {
02244 cur = nextVObject( &iter );
02245 curname = vObjectName( cur );
02246 Q_ASSERT( curname );
02247 if ( ( curname[0] == 'X' && curname[1] == '-' ) &&
02248 strcmp( curname, ICOrganizerProp ) != 0 ) {
02249
02250
02251 i->setNonKDECustomProperty(
02252 curname, QString::fromLocal8Bit( s = fakeCString( vObjectUStringZValue( cur ) ) ) );
02253 deleteStr( s );
02254 }
02255 }
02256 }
02257
02258 void VCalFormat::writeCustomProperties( VObject *o, const Incidence::Ptr &i )
02259 {
02260 const QMap<QByteArray, QString> custom = i->customProperties();
02261 for ( QMap<QByteArray, QString>::ConstIterator c = custom.begin();
02262 c != custom.end(); ++c ) {
02263 if ( d->mManuallyWrittenExtensionFields.contains( c.key() ) ) {
02264 continue;
02265 }
02266
02267 addPropValue( o, c.key(), c.value().toLocal8Bit() );
02268 }
02269 }
02270
02271 void VCalFormat::virtual_hook( int id, void *data )
02272 {
02273 Q_UNUSED( id );
02274 Q_UNUSED( data );
02275 Q_ASSERT( false );
02276 }