00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00038 #include "vcalformat.h"
00039 #include "calendar.h"
00040 #include "versit/vcc.h"
00041 #include "versit/vobject.h"
00042
00043 #include <kdebug.h>
00044 #include <kdatetime.h>
00045 #include <klocale.h>
00046
00047 #include <QtCore/QString>
00048 #include <QtCore/QRegExp>
00049 #include <QtCore/QFile>
00050 #include <QtCore/QByteArray>
00051 #include <QtGui/QTextDocument>
00052
00053 using namespace KCal;
00054
00059
00060 class KCal::VCalFormat::Private
00061 {
00062 public:
00063 Calendar *mCalendar;
00064 Event::List mEventsRelate;
00065 Todo::List mTodosRelate;
00066 };
00067
00068
00069 VCalFormat::VCalFormat() : d( new KCal::VCalFormat::Private )
00070 {
00071 }
00072
00073 VCalFormat::~VCalFormat()
00074 {
00075 delete d;
00076 }
00077
00078 bool VCalFormat::load( Calendar *calendar, const QString &fileName )
00079 {
00080 d->mCalendar = calendar;
00081
00082 clearException();
00083
00084 kDebug() << fileName;
00085
00086 VObject *vcal = 0;
00087
00088
00089
00090 vcal = Parse_MIME_FromFileName( const_cast<char *>( QFile::encodeName( fileName ).data() ) );
00091
00092 if ( !vcal ) {
00093 setException( new ErrorFormat( ErrorFormat::CalVersionUnknown ) );
00094 return false;
00095 }
00096
00097
00098
00099
00100 populate( vcal );
00101
00102
00103 cleanVObjects( vcal );
00104 cleanStrTbl();
00105
00106 return true;
00107 }
00108
00109 bool VCalFormat::save( Calendar *calendar, const QString &fileName )
00110 {
00111 d->mCalendar = calendar;
00112
00113 QString tmpStr;
00114 VObject *vcal, *vo;
00115
00116 kDebug() << fileName;
00117
00118 vcal = newVObject( VCCalProp );
00119
00120
00121 addPropValue( vcal, VCProdIdProp, productId().toLatin1() );
00122 addPropValue( vcal, VCVersionProp, _VCAL_VERSION );
00123
00124
00125 Todo::List todoList = d->mCalendar->rawTodos();
00126 Todo::List::ConstIterator it;
00127 for ( it = todoList.constBegin(); it != todoList.constEnd(); ++it ) {
00128 vo = eventToVTodo( *it );
00129 addVObjectProp( vcal, vo );
00130 }
00131
00132
00133 Event::List events = d->mCalendar->rawEvents();
00134 Event::List::ConstIterator it2;
00135 for ( it2 = events.constBegin(); it2 != events.constEnd(); ++it2 ) {
00136 vo = eventToVEvent( *it2 );
00137 addVObjectProp( vcal, vo );
00138 }
00139
00140 writeVObjectToFile( QFile::encodeName( fileName ).data(), vcal );
00141 cleanVObjects( vcal );
00142 cleanStrTbl();
00143
00144 if ( QFile::exists( fileName ) ) {
00145 return true;
00146 } else {
00147 return false;
00148 }
00149
00150 return false;
00151 }
00152
00153 bool VCalFormat::fromString( Calendar *calendar, const QString &string )
00154 {
00155 return fromRawString( calendar, string.toUtf8() );
00156 }
00157
00158 bool VCalFormat::fromRawString( Calendar *calendar, const QByteArray &string )
00159 {
00160 d->mCalendar = calendar;
00161
00162 if ( !string.size() ) {
00163 return false;
00164 }
00165
00166 VObject *vcal = Parse_MIME( string.data(), string.size() );
00167 if ( !vcal ) {
00168 return false;
00169 }
00170
00171 VObjectIterator i;
00172 VObject *curvo;
00173 initPropIterator( &i, vcal );
00174
00175
00176 do {
00177 curvo = nextVObject( &i );
00178 } while ( strcmp( vObjectName( curvo ), VCEventProp ) &&
00179 strcmp( vObjectName( curvo ), VCTodoProp ) );
00180
00181 if ( strcmp( vObjectName( curvo ), VCEventProp ) == 0 ) {
00182 Event *event = VEventToEvent( curvo );
00183 calendar->addEvent( event );
00184 } else {
00185 kDebug() << "Unknown object type.";
00186 deleteVObject( vcal );
00187 return false;
00188 }
00189
00190 deleteVObject( vcal );
00191
00192 return true;
00193 }
00194
00195 QString VCalFormat::toString( Calendar *calendar )
00196 {
00197
00198 d->mCalendar = calendar;
00199
00200 VObject *vcal = newVObject( VCCalProp );
00201
00202 addPropValue( vcal, VCProdIdProp, CalFormat::productId().toLatin1() );
00203 addPropValue( vcal, VCVersionProp, _VCAL_VERSION );
00204
00205
00206 Event::List events = calendar->events();
00207 if( events.isEmpty() ) {
00208 cleanVObject ( vcal );
00209 return QString();
00210 }
00211 Event *event = events.first();
00212 if ( !event ) {
00213 cleanVObject ( vcal );
00214 return QString();
00215 }
00216 VObject *vevent = eventToVEvent( event );
00217
00218 addVObjectProp( vcal, vevent );
00219
00220 char *buf = writeMemVObject( 0, 0, vcal );
00221
00222 QString result( buf );
00223
00224 cleanVObject( vcal );
00225
00226 return result;
00227 }
00228
00229 VObject *VCalFormat::eventToVTodo( const Todo *anEvent )
00230 {
00231 VObject *vtodo;
00232 QString tmpStr;
00233
00234 vtodo = newVObject( VCTodoProp );
00235
00236
00237 if ( anEvent->hasDueDate() ) {
00238 tmpStr = kDateTimeToISO( anEvent->dtDue(), !anEvent->allDay() );
00239 addPropValue( vtodo, VCDueProp, tmpStr.toLocal8Bit() );
00240 }
00241
00242
00243 if ( anEvent->hasStartDate() ) {
00244 tmpStr = kDateTimeToISO( anEvent->dtStart(), !anEvent->allDay() );
00245 addPropValue( vtodo, VCDTstartProp, tmpStr.toLocal8Bit() );
00246 }
00247
00248
00249 tmpStr = kDateTimeToISO( anEvent->created() );
00250 addPropValue( vtodo, VCDCreatedProp, tmpStr.toLocal8Bit() );
00251
00252
00253 addPropValue( vtodo, VCUniqueStringProp,
00254 anEvent->uid().toLocal8Bit() );
00255
00256
00257 tmpStr.sprintf( "%i", anEvent->revision() );
00258 addPropValue( vtodo, VCSequenceProp, tmpStr.toLocal8Bit() );
00259
00260
00261 tmpStr = kDateTimeToISO( anEvent->lastModified() );
00262 addPropValue( vtodo, VCLastModifiedProp, tmpStr.toLocal8Bit() );
00263
00264
00265
00266 if ( !anEvent->organizer().email().isEmpty() ) {
00267 tmpStr = "MAILTO:" + anEvent->organizer().email();
00268 addPropValue( vtodo, ICOrganizerProp, tmpStr.toLocal8Bit() );
00269 }
00270
00271
00272 if ( anEvent->attendeeCount() > 0 ) {
00273 Attendee::List::ConstIterator it;
00274 Attendee *curAttendee;
00275 for ( it = anEvent->attendees().begin(); it != anEvent->attendees().end();
00276 ++it ) {
00277 curAttendee = *it;
00278 if ( !curAttendee->email().isEmpty() &&
00279 !curAttendee->name().isEmpty() ) {
00280 tmpStr = "MAILTO:" + curAttendee->name() + " <" + curAttendee->email() + '>';
00281 } else if ( curAttendee->name().isEmpty() ) {
00282 tmpStr = "MAILTO: " + curAttendee->email();
00283 } else if ( curAttendee->email().isEmpty() ) {
00284 tmpStr = "MAILTO: " + curAttendee->name();
00285 } else if ( curAttendee->name().isEmpty() && curAttendee->email().isEmpty() ) {
00286 kDebug() << "warning! this Event has an attendee w/o name or email!";
00287 }
00288 VObject *aProp = addPropValue( vtodo, VCAttendeeProp, tmpStr.toLocal8Bit() );
00289 addPropValue( aProp, VCRSVPProp, curAttendee->RSVP() ? "TRUE" : "FALSE" );
00290 addPropValue( aProp, VCStatusProp, writeStatus( curAttendee->status() ) );
00291 }
00292 }
00293
00294
00295 if ( !anEvent->description().isEmpty() ) {
00296 VObject *d = addPropValue( vtodo, VCDescriptionProp,
00297 anEvent->description().toLocal8Bit() );
00298 if ( anEvent->description().indexOf( '\n' ) != -1 ) {
00299 addPropValue( d, VCEncodingProp, VCQuotedPrintableProp );
00300 }
00301 }
00302
00303
00304 if ( !anEvent->summary().isEmpty() ) {
00305 addPropValue( vtodo, VCSummaryProp, anEvent->summary().toLocal8Bit() );
00306 }
00307
00308
00309 if ( !anEvent->location().isEmpty() ) {
00310 addPropValue( vtodo, VCLocationProp, anEvent->location().toLocal8Bit() );
00311 }
00312
00313
00314
00315 addPropValue( vtodo, VCStatusProp, anEvent->isCompleted() ? "COMPLETED" : "NEEDS_ACTION" );
00316
00317
00318 if ( anEvent->hasCompletedDate() ) {
00319 tmpStr = kDateTimeToISO( anEvent->completed() );
00320 addPropValue( vtodo, VCCompletedProp, tmpStr.toLocal8Bit() );
00321 }
00322
00323
00324 tmpStr.sprintf( "%i", anEvent->priority() );
00325 addPropValue( vtodo, VCPriorityProp, tmpStr.toLocal8Bit() );
00326
00327
00328 if ( anEvent->relatedTo() ) {
00329 addPropValue( vtodo, VCRelatedToProp,
00330 anEvent->relatedTo()->uid().toLocal8Bit() );
00331 }
00332
00333
00334 const QStringList tmpStrList = anEvent->categories();
00335 tmpStr = "";
00336 QString catStr;
00337 QStringList::const_iterator its;
00338 for ( its = tmpStrList.constBegin(); its != tmpStrList.constEnd(); ++its ) {
00339 catStr = *its;
00340 if ( catStr[0] == ' ' ) {
00341 tmpStr += catStr.mid( 1 );
00342 } else {
00343 tmpStr += catStr;
00344 }
00345
00346
00347
00348 tmpStr += ';';
00349 }
00350 if ( !tmpStr.isEmpty() ) {
00351 tmpStr.truncate( tmpStr.length() - 1 );
00352 addPropValue( vtodo, VCCategoriesProp, tmpStr.toLocal8Bit() );
00353 }
00354
00355
00356 Alarm::List::ConstIterator it;
00357 for ( it = anEvent->alarms().begin(); it != anEvent->alarms().end(); ++it ) {
00358 Alarm *alarm = *it;
00359 if ( alarm->enabled() ) {
00360 VObject *a = addProp( vtodo, VCDAlarmProp );
00361 tmpStr = kDateTimeToISO( alarm->time() );
00362 addPropValue( a, VCRunTimeProp, tmpStr.toLocal8Bit() );
00363 addPropValue( a, VCRepeatCountProp, "1" );
00364 addPropValue( a, VCDisplayStringProp, "beep!" );
00365 if ( alarm->type() == Alarm::Audio ) {
00366 a = addProp( vtodo, VCAAlarmProp );
00367 addPropValue( a, VCRunTimeProp, tmpStr.toLocal8Bit() );
00368 addPropValue( a, VCRepeatCountProp, "1" );
00369 addPropValue( a, VCAudioContentProp, QFile::encodeName( alarm->audioFile() ) );
00370 } else if ( alarm->type() == Alarm::Procedure ) {
00371 a = addProp( vtodo, VCPAlarmProp );
00372 addPropValue( a, VCRunTimeProp, tmpStr.toLocal8Bit() );
00373 addPropValue( a, VCRepeatCountProp, "1" );
00374 addPropValue( a, VCProcedureNameProp, QFile::encodeName( alarm->programFile() ) );
00375 }
00376 }
00377 }
00378
00379 QString pilotId = anEvent->nonKDECustomProperty( KPilotIdProp );
00380 if ( !pilotId.isEmpty() ) {
00381
00382 addPropValue( vtodo, KPilotIdProp, pilotId.toLocal8Bit() );
00383 addPropValue( vtodo, KPilotStatusProp,
00384 anEvent->nonKDECustomProperty( KPilotStatusProp ).toLocal8Bit() );
00385 }
00386
00387 return vtodo;
00388 }
00389
00390 VObject *VCalFormat::eventToVEvent( const Event *anEvent )
00391 {
00392 VObject *vevent;
00393 QString tmpStr;
00394
00395 vevent = newVObject( VCEventProp );
00396
00397
00398 tmpStr = kDateTimeToISO( anEvent->dtStart(), !anEvent->allDay() );
00399 addPropValue( vevent, VCDTstartProp, tmpStr.toLocal8Bit() );
00400
00401
00402
00403 if ( anEvent->dtStart() != anEvent->dtEnd() ) {
00404 tmpStr = kDateTimeToISO( anEvent->dtEnd(), !anEvent->allDay() );
00405 addPropValue( vevent, VCDTendProp, tmpStr.toLocal8Bit() );
00406 }
00407
00408
00409 tmpStr = kDateTimeToISO( anEvent->created() );
00410 addPropValue( vevent, VCDCreatedProp, tmpStr.toLocal8Bit() );
00411
00412
00413 addPropValue( vevent, VCUniqueStringProp,
00414 anEvent->uid().toLocal8Bit() );
00415
00416
00417 tmpStr.sprintf( "%i", anEvent->revision() );
00418 addPropValue( vevent, VCSequenceProp, tmpStr.toLocal8Bit() );
00419
00420
00421 tmpStr = kDateTimeToISO( anEvent->lastModified() );
00422 addPropValue( vevent, VCLastModifiedProp, tmpStr.toLocal8Bit() );
00423
00424
00425
00426 if ( !anEvent->organizer().email().isEmpty() ) {
00427 tmpStr = "MAILTO:" + anEvent->organizer().email();
00428 addPropValue( vevent, ICOrganizerProp, tmpStr.toLocal8Bit() );
00429 }
00430
00431
00432 if ( anEvent->attendeeCount() > 0 ) {
00433 Attendee::List::ConstIterator it;
00434 for ( it = anEvent->attendees().constBegin(); it != anEvent->attendees().constEnd();
00435 ++it ) {
00436 Attendee *curAttendee = *it;
00437 if ( !curAttendee->email().isEmpty() && !curAttendee->name().isEmpty() ) {
00438 tmpStr = "MAILTO:" + curAttendee->name() + " <" + curAttendee->email() + '>';
00439 } else if ( curAttendee->name().isEmpty() ) {
00440 tmpStr = "MAILTO: " + curAttendee->email();
00441 } else if ( curAttendee->email().isEmpty() ) {
00442 tmpStr = "MAILTO: " + curAttendee->name();
00443 } else if ( curAttendee->name().isEmpty() && curAttendee->email().isEmpty() ) {
00444 kDebug() << "warning! this Event has an attendee w/o name or email!";
00445 }
00446 VObject *aProp = addPropValue( vevent, VCAttendeeProp, tmpStr.toLocal8Bit() );
00447 addPropValue( aProp, VCRSVPProp, curAttendee->RSVP() ? "TRUE" : "FALSE" );
00448 addPropValue( aProp, VCStatusProp, writeStatus( curAttendee->status() ) );
00449 }
00450 }
00451
00452
00453 const Recurrence *recur = anEvent->recurrence();
00454 if ( recur->recurs() ) {
00455 bool validRecur = true;
00456 QString tmpStr2;
00457 switch ( recur->recurrenceType() ) {
00458 case Recurrence::rDaily:
00459 tmpStr.sprintf( "D%i ", recur->frequency() );
00460 break;
00461 case Recurrence::rWeekly:
00462 tmpStr.sprintf( "W%i ", recur->frequency() );
00463 for ( int i = 0; i < 7; ++i ) {
00464 QBitArray days ( recur->days() );
00465 if ( days.testBit(i) ) {
00466 tmpStr += dayFromNum( i );
00467 }
00468 }
00469 break;
00470 case Recurrence::rMonthlyPos:
00471 {
00472 tmpStr.sprintf( "MP%i ", recur->frequency() );
00473
00474 QList<RecurrenceRule::WDayPos> tmpPositions = recur->monthPositions();
00475 for ( QList<RecurrenceRule::WDayPos>::ConstIterator posit = tmpPositions.constBegin();
00476 posit != tmpPositions.constEnd(); ++posit ) {
00477 int pos = (*posit).pos();
00478 tmpStr2.sprintf( "%i", ( pos > 0 ) ? pos : (-pos) );
00479 if ( pos < 0 ) {
00480 tmpStr2 += "- ";
00481 } else {
00482 tmpStr2 += "+ ";
00483 }
00484 tmpStr += tmpStr2;
00485 tmpStr += dayFromNum( (*posit).day() - 1 );
00486 }
00487 break;
00488 }
00489 case Recurrence::rMonthlyDay:
00490 {
00491 tmpStr.sprintf( "MD%i ", recur->frequency() );
00492
00493 const QList<int> tmpDays = recur->monthDays();
00494 for ( QList<int>::ConstIterator tmpDay = tmpDays.constBegin();
00495 tmpDay != tmpDays.constEnd(); ++tmpDay ) {
00496 tmpStr2.sprintf( "%i ", *tmpDay );
00497 tmpStr += tmpStr2;
00498 }
00499 break;
00500 }
00501 case Recurrence::rYearlyMonth:
00502 {
00503 tmpStr.sprintf( "YM%i ", recur->frequency() );
00504
00505
00506 const QList<int> months = recur->yearMonths();
00507 for ( QList<int>::ConstIterator mit = months.constBegin();
00508 mit != months.constEnd(); ++mit ) {
00509 tmpStr2.sprintf( "%i ", *mit );
00510 tmpStr += tmpStr2;
00511 }
00512 break;
00513 }
00514 case Recurrence::rYearlyDay:
00515 {
00516 tmpStr.sprintf( "YD%i ", recur->frequency() );
00517
00518 const QList<int> tmpDays = recur->yearDays();
00519 for ( QList<int>::ConstIterator tmpDay = tmpDays.begin();
00520 tmpDay != tmpDays.end(); ++tmpDay ) {
00521 tmpStr2.sprintf( "%i ", *tmpDay );
00522 tmpStr += tmpStr2;
00523 }
00524 break;
00525 }
00526 default:
00527
00528 kDebug() << "ERROR, it should never get here in eventToVEvent!";
00529 validRecur = false;
00530 break;
00531 }
00532
00533 if ( recur->duration() > 0 ) {
00534 tmpStr2.sprintf( "#%i", recur->duration() );
00535 tmpStr += tmpStr2;
00536 } else if ( recur->duration() == -1 ) {
00537 tmpStr += "#0";
00538 } else {
00539 tmpStr += kDateTimeToISO( recur->endDateTime(), false );
00540 }
00541
00542
00543 if ( validRecur ) {
00544 addPropValue( vevent, VCRRuleProp, tmpStr.toLocal8Bit() );
00545 }
00546
00547 }
00548
00549
00550 DateList dateList = recur->exDates();
00551 DateList::ConstIterator it;
00552 QString tmpStr2;
00553
00554 for ( it = dateList.constBegin(); it != dateList.constEnd(); ++it ) {
00555 tmpStr = qDateToISO(*it) + ';';
00556 tmpStr2 += tmpStr;
00557 }
00558 if ( !tmpStr2.isEmpty() ) {
00559 tmpStr2.truncate( tmpStr2.length() - 1 );
00560 addPropValue( vevent, VCExpDateProp, tmpStr2.toLocal8Bit() );
00561 }
00562
00563
00564 if ( !anEvent->description().isEmpty() ) {
00565 VObject *d = addPropValue( vevent, VCDescriptionProp,
00566 anEvent->description().toLocal8Bit() );
00567 if ( anEvent->description().indexOf( '\n' ) != -1 ) {
00568 addPropValue( d, VCEncodingProp, VCQuotedPrintableProp );
00569 }
00570 }
00571
00572
00573 if ( !anEvent->summary().isEmpty() ) {
00574 addPropValue( vevent, VCSummaryProp, anEvent->summary().toLocal8Bit() );
00575 }
00576
00577
00578 if ( !anEvent->location().isEmpty() ) {
00579 addPropValue( vevent, VCLocationProp, anEvent->location().toLocal8Bit() );
00580 }
00581
00582
00583
00584
00585
00586
00587 const char *text = 0;
00588 switch ( anEvent->secrecy() ) {
00589 case Incidence::SecrecyPublic:
00590 text = "PUBLIC";
00591 break;
00592 case Incidence::SecrecyPrivate:
00593 text = "PRIVATE";
00594 break;
00595 case Incidence::SecrecyConfidential:
00596 text = "CONFIDENTIAL";
00597 break;
00598 }
00599 if ( text ) {
00600 addPropValue( vevent, VCClassProp, text );
00601 }
00602
00603
00604 QStringList tmpStrList = anEvent->categories();
00605 tmpStr = "";
00606 QString catStr;
00607 for ( QStringList::const_iterator it = tmpStrList.constBegin(); it != tmpStrList.constEnd();
00608 ++it ) {
00609 catStr = *it;
00610 if ( catStr[0] == ' ' ) {
00611 tmpStr += catStr.mid( 1 );
00612 } else {
00613 tmpStr += catStr;
00614 }
00615
00616
00617
00618 tmpStr += ';';
00619 }
00620 if ( !tmpStr.isEmpty() ) {
00621 tmpStr.truncate( tmpStr.length() - 1 );
00622 addPropValue( vevent, VCCategoriesProp, tmpStr.toLocal8Bit() );
00623 }
00624
00625
00626
00627 Attachment::List attachments = anEvent->attachments();
00628 Attachment::List::ConstIterator atIt;
00629 for ( atIt = attachments.constBegin(); atIt != attachments.constEnd(); ++atIt ) {
00630 addPropValue( vevent, VCAttachProp, (*atIt)->uri().toLocal8Bit() );
00631 }
00632
00633
00634 tmpStrList = anEvent->resources();
00635 tmpStr = tmpStrList.join( ";" );
00636 if ( !tmpStr.isEmpty() ) {
00637 addPropValue( vevent, VCResourcesProp, tmpStr.toLocal8Bit() );
00638 }
00639
00640
00641 Alarm::List::ConstIterator it2;
00642 for ( it2 = anEvent->alarms().constBegin(); it2 != anEvent->alarms().constEnd(); ++it2 ) {
00643 Alarm *alarm = *it2;
00644 if ( alarm->enabled() ) {
00645 VObject *a = addProp( vevent, VCDAlarmProp );
00646 tmpStr = kDateTimeToISO( alarm->time() );
00647 addPropValue( a, VCRunTimeProp, tmpStr.toLocal8Bit() );
00648 addPropValue( a, VCRepeatCountProp, "1" );
00649 addPropValue( a, VCDisplayStringProp, "beep!" );
00650 if ( alarm->type() == Alarm::Audio ) {
00651 a = addProp( vevent, VCAAlarmProp );
00652 addPropValue( a, VCRunTimeProp, tmpStr.toLocal8Bit() );
00653 addPropValue( a, VCRepeatCountProp, "1" );
00654 addPropValue( a, VCAudioContentProp, QFile::encodeName( alarm->audioFile() ) );
00655 }
00656 if ( alarm->type() == Alarm::Procedure ) {
00657 a = addProp( vevent, VCPAlarmProp );
00658 addPropValue( a, VCRunTimeProp, tmpStr.toLocal8Bit() );
00659 addPropValue( a, VCRepeatCountProp, "1" );
00660 addPropValue( a, VCProcedureNameProp, QFile::encodeName( alarm->programFile() ) );
00661 }
00662 }
00663 }
00664
00665
00666 tmpStr.sprintf( "%i", anEvent->priority() );
00667 addPropValue( vevent, VCPriorityProp, tmpStr.toLocal8Bit() );
00668
00669
00670 tmpStr.sprintf( "%i", anEvent->transparency() );
00671 addPropValue( vevent, VCTranspProp, tmpStr.toLocal8Bit() );
00672
00673
00674 if ( anEvent->relatedTo() ) {
00675 addPropValue( vevent, VCRelatedToProp, anEvent->relatedTo()->uid().toLocal8Bit() );
00676 }
00677
00678 QString pilotId = anEvent->nonKDECustomProperty( KPilotIdProp );
00679 if ( !pilotId.isEmpty() ) {
00680
00681 addPropValue( vevent, KPilotIdProp, pilotId.toLocal8Bit() );
00682 addPropValue( vevent, KPilotStatusProp,
00683 anEvent->nonKDECustomProperty( KPilotStatusProp ).toLocal8Bit() );
00684 }
00685
00686 return vevent;
00687 }
00688
00689 Todo *VCalFormat::VTodoToEvent( VObject *vtodo )
00690 {
00691 VObject *vo;
00692 VObjectIterator voi;
00693 char *s;
00694
00695 Todo *anEvent = new Todo;
00696
00697
00698 if ( ( vo = isAPropertyOf( vtodo, VCDCreatedProp ) ) != 0 ) {
00699 anEvent->setCreated( ISOToKDateTime( s = fakeCString( vObjectUStringZValue( vo ) ) ) );
00700 deleteStr( s );
00701 }
00702
00703
00704 vo = isAPropertyOf( vtodo, VCUniqueStringProp );
00705
00706
00707 if ( vo ) {
00708 anEvent->setUid( s = fakeCString( vObjectUStringZValue( vo ) ) );
00709 deleteStr( s );
00710 }
00711
00712
00713 if ( ( vo = isAPropertyOf( vtodo, VCLastModifiedProp ) ) != 0 ) {
00714 anEvent->setLastModified( ISOToKDateTime( s = fakeCString( vObjectUStringZValue( vo ) ) ) );
00715 deleteStr( s );
00716 } else {
00717 anEvent->setLastModified( KDateTime::currentUtcDateTime() );
00718 }
00719
00720
00721
00722 if ( ( vo = isAPropertyOf( vtodo, ICOrganizerProp ) ) != 0 ) {
00723 anEvent->setOrganizer( s = fakeCString( vObjectUStringZValue( vo ) ) );
00724 deleteStr( s );
00725 } else {
00726 anEvent->setOrganizer( d->mCalendar->owner() );
00727 }
00728
00729
00730 initPropIterator( &voi, vtodo );
00731 while ( moreIteration( &voi ) ) {
00732 vo = nextVObject( &voi );
00733 if ( strcmp( vObjectName( vo ), VCAttendeeProp ) == 0 ) {
00734 Attendee *a;
00735 VObject *vp;
00736 s = fakeCString( vObjectUStringZValue( vo ) );
00737 QString tmpStr = QString::fromLocal8Bit( s );
00738 deleteStr( s );
00739 tmpStr = tmpStr.simplified();
00740 int emailPos1, emailPos2;
00741 if ( ( emailPos1 = tmpStr.indexOf( '<' ) ) > 0 ) {
00742
00743 emailPos2 = tmpStr.lastIndexOf( '>' );
00744 a = new Attendee( tmpStr.left( emailPos1 - 1 ),
00745 tmpStr.mid( emailPos1 + 1,
00746 emailPos2 - ( emailPos1 + 1 ) ) );
00747 } else if ( tmpStr.indexOf( '@' ) > 0 ) {
00748
00749 a = new Attendee( 0, tmpStr );
00750 } else {
00751
00752
00753 QString email = tmpStr.replace( ' ', '.' );
00754 a = new Attendee( tmpStr, email );
00755 }
00756
00757
00758 if ( ( vp = isAPropertyOf( vo, VCRSVPProp ) ) != 0 ) {
00759 a->setRSVP( vObjectStringZValue( vp ) );
00760 }
00761
00762 if ( ( vp = isAPropertyOf( vo, VCStatusProp ) ) != 0 ) {
00763 a->setStatus( readStatus( vObjectStringZValue( vp ) ) );
00764 }
00765
00766 anEvent->addAttendee( a );
00767 }
00768 }
00769
00770
00771 if ( ( vo = isAPropertyOf( vtodo, VCDescriptionProp ) ) != 0 ) {
00772 s = fakeCString( vObjectUStringZValue( vo ) );
00773 anEvent->setDescription( QString::fromLocal8Bit( s ), Qt::mightBeRichText( s ) );
00774 deleteStr( s );
00775 }
00776
00777
00778 if ( ( vo = isAPropertyOf( vtodo, VCSummaryProp ) ) ) {
00779 s = fakeCString( vObjectUStringZValue( vo ) );
00780 anEvent->setSummary( QString::fromLocal8Bit( s ), Qt::mightBeRichText( s ) );
00781 deleteStr( s );
00782 }
00783
00784
00785 if ( ( vo = isAPropertyOf( vtodo, VCLocationProp ) ) != 0 ) {
00786 s = fakeCString( vObjectUStringZValue( vo ) );
00787 anEvent->setLocation( QString::fromLocal8Bit( s ), Qt::mightBeRichText( s ) );
00788 deleteStr( s );
00789 }
00790
00791
00792
00793 if ( ( vo = isAPropertyOf( vtodo, VCStatusProp ) ) != 0 ) {
00794 s = fakeCString( vObjectUStringZValue( vo ) );
00795 if ( s && strcmp( s, "COMPLETED" ) == 0 ) {
00796 anEvent->setCompleted( true );
00797 } else {
00798 anEvent->setCompleted( false );
00799 }
00800 deleteStr( s );
00801 } else {
00802 anEvent->setCompleted( false );
00803 }
00804
00805
00806 if ( ( vo = isAPropertyOf( vtodo, VCCompletedProp ) ) != 0 ) {
00807 anEvent->setCompleted( ISOToKDateTime( s = fakeCString( vObjectUStringZValue( vo ) ) ) );
00808 deleteStr( s );
00809 }
00810
00811
00812 if ( ( vo = isAPropertyOf( vtodo, VCPriorityProp ) ) ) {
00813 s = fakeCString( vObjectUStringZValue( vo ) );
00814 if ( s ) {
00815 anEvent->setPriority( atoi( s ) );
00816 deleteStr( s );
00817 }
00818 }
00819
00820
00821 if ( ( vo = isAPropertyOf( vtodo, VCDueProp ) ) != 0 ) {
00822 anEvent->setDtDue( ISOToKDateTime( s = fakeCString( vObjectUStringZValue( vo ) ) ) );
00823 deleteStr( s );
00824 anEvent->setHasDueDate( true );
00825 } else {
00826 anEvent->setHasDueDate( false );
00827 }
00828
00829
00830 if ( ( vo = isAPropertyOf( vtodo, VCDTstartProp ) ) != 0 ) {
00831 anEvent->setDtStart( ISOToKDateTime( s = fakeCString( vObjectUStringZValue( vo ) ) ) );
00832 deleteStr( s );
00833 anEvent->setHasStartDate( true );
00834 } else {
00835 anEvent->setHasStartDate( false );
00836 }
00837
00838
00839 if ( ( vo = isAPropertyOf( vtodo, VCDAlarmProp ) ) ) {
00840 Alarm *alarm = anEvent->newAlarm();
00841 VObject *a;
00842 if ( ( a = isAPropertyOf( vo, VCRunTimeProp ) ) ) {
00843 alarm->setTime( ISOToKDateTime( s = fakeCString( vObjectUStringZValue( a ) ) ) );
00844 deleteStr( s );
00845 }
00846 alarm->setEnabled( true );
00847 if ( ( vo = isAPropertyOf( vtodo, VCPAlarmProp ) ) ) {
00848 if ( ( a = isAPropertyOf( vo, VCProcedureNameProp ) ) ) {
00849 s = fakeCString( vObjectUStringZValue( a ) );
00850 alarm->setProcedureAlarm( QFile::decodeName( s ) );
00851 deleteStr( s );
00852 }
00853 }
00854 if ( ( vo = isAPropertyOf( vtodo, VCAAlarmProp ) ) ) {
00855 if ( ( a = isAPropertyOf( vo, VCAudioContentProp ) ) ) {
00856 s = fakeCString( vObjectUStringZValue( a ) );
00857 alarm->setAudioAlarm( QFile::decodeName( s ) );
00858 deleteStr( s );
00859 }
00860 }
00861 }
00862
00863
00864 if ( ( vo = isAPropertyOf( vtodo, VCRelatedToProp ) ) != 0 ) {
00865 anEvent->setRelatedToUid( s = fakeCString( vObjectUStringZValue( vo ) ) );
00866 deleteStr( s );
00867 d->mTodosRelate.append( anEvent );
00868 }
00869
00870
00871 if ( ( vo = isAPropertyOf( vtodo, VCCategoriesProp ) ) != 0 ) {
00872 s = fakeCString( vObjectUStringZValue( vo ) );
00873 QString categories = QString::fromLocal8Bit( s );
00874 deleteStr( s );
00875 QStringList tmpStrList = categories.split( ';' );
00876 anEvent->setCategories( tmpStrList );
00877 }
00878
00879
00880 if ( ( vo = isAPropertyOf( vtodo, KPilotIdProp ) ) ) {
00881 anEvent->setNonKDECustomProperty(
00882 KPilotIdProp, QString::fromLocal8Bit( s = fakeCString( vObjectUStringZValue( vo ) ) ) );
00883 deleteStr( s );
00884 if ( ( vo = isAPropertyOf( vtodo, KPilotStatusProp ) ) ) {
00885 anEvent->setNonKDECustomProperty(
00886 KPilotStatusProp, QString::fromLocal8Bit( s = fakeCString( vObjectUStringZValue( vo ) ) ) );
00887 deleteStr( s );
00888 } else {
00889 anEvent->setNonKDECustomProperty( KPilotStatusProp, QString::number( SYNCMOD ) );
00890 }
00891 }
00892
00893 return anEvent;
00894 }
00895
00896 Event *VCalFormat::VEventToEvent( VObject *vevent )
00897 {
00898 VObject *vo;
00899 VObjectIterator voi;
00900 char *s;
00901
00902 Event *anEvent = new Event;
00903
00904
00905 if ( ( vo = isAPropertyOf( vevent, VCDCreatedProp ) ) != 0 ) {
00906 anEvent->setCreated( ISOToKDateTime( s = fakeCString( vObjectUStringZValue( vo ) ) ) );
00907 deleteStr( s );
00908 }
00909
00910
00911 vo = isAPropertyOf( vevent, VCUniqueStringProp );
00912
00913
00914 if ( vo ) {
00915 anEvent->setUid( s = fakeCString( vObjectUStringZValue( vo ) ) );
00916 deleteStr( s );
00917 }
00918
00919
00920
00921 anEvent->setRevision( 0 );
00922 if ( ( vo = isAPropertyOf( vevent, VCSequenceProp ) ) != 0 ) {
00923 s = fakeCString( vObjectUStringZValue( vo ) );
00924 if ( s ) {
00925 anEvent->setRevision( atoi( s ) );
00926 deleteStr( s );
00927 }
00928 }
00929
00930
00931 if ( ( vo = isAPropertyOf( vevent, VCLastModifiedProp ) ) != 0 ) {
00932 anEvent->setLastModified( ISOToKDateTime( s = fakeCString( vObjectUStringZValue( vo ) ) ) );
00933 deleteStr( s );
00934 } else {
00935 anEvent->setLastModified( KDateTime::currentUtcDateTime() );
00936 }
00937
00938
00939
00940 if ( ( vo = isAPropertyOf( vevent, ICOrganizerProp ) ) != 0 ) {
00941
00942 anEvent->setOrganizer( s = fakeCString( vObjectUStringZValue( vo ) ) );
00943 deleteStr( s );
00944 } else {
00945 anEvent->setOrganizer( d->mCalendar->owner() );
00946 }
00947
00948
00949 initPropIterator( &voi, vevent );
00950 while ( moreIteration( &voi ) ) {
00951 vo = nextVObject( &voi );
00952 if ( strcmp( vObjectName( vo ), VCAttendeeProp ) == 0 ) {
00953 Attendee *a;
00954 VObject *vp;
00955 s = fakeCString( vObjectUStringZValue( vo ) );
00956 QString tmpStr = QString::fromLocal8Bit( s );
00957 deleteStr( s );
00958 tmpStr = tmpStr.simplified();
00959 int emailPos1, emailPos2;
00960 if ( ( emailPos1 = tmpStr.indexOf( '<' ) ) > 0 ) {
00961
00962 emailPos2 = tmpStr.lastIndexOf( '>' );
00963 a = new Attendee( tmpStr.left( emailPos1 - 1 ),
00964 tmpStr.mid( emailPos1 + 1,
00965 emailPos2 - ( emailPos1 + 1 ) ) );
00966 } else if ( tmpStr.indexOf( '@' ) > 0 ) {
00967
00968 a = new Attendee( 0, tmpStr );
00969 } else {
00970
00971 QString email = tmpStr.replace( ' ', '.' );
00972 a = new Attendee( tmpStr, email );
00973 }
00974
00975
00976 if ( ( vp = isAPropertyOf( vo, VCRSVPProp ) ) != 0 ) {
00977 a->setRSVP( vObjectStringZValue( vp ) );
00978 }
00979
00980 if ( ( vp = isAPropertyOf( vo, VCStatusProp ) ) != 0 ) {
00981 a->setStatus( readStatus( vObjectStringZValue( vp ) ) );
00982 }
00983
00984 anEvent->addAttendee( a );
00985 }
00986 }
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996
00997 anEvent->setAllDay( false );
00998
00999
01000 if ( ( vo = isAPropertyOf( vevent, VCDTstartProp ) ) != 0 ) {
01001 anEvent->setDtStart( ISOToKDateTime( s = fakeCString( vObjectUStringZValue( vo ) ) ) );
01002 deleteStr( s );
01003 if ( anEvent->dtStart().time().isNull() ) {
01004 anEvent->setAllDay( true );
01005 }
01006 }
01007
01008
01009 if ( ( vo = isAPropertyOf( vevent, VCDTendProp ) ) != 0 ) {
01010 anEvent->setDtEnd( ISOToKDateTime( s = fakeCString( vObjectUStringZValue( vo ) ) ) );
01011 deleteStr( s );
01012 if ( anEvent->dtEnd().time().isNull() ) {
01013 anEvent->setAllDay( true );
01014 }
01015 }
01016
01017
01018
01019 if ( !( vo = isAPropertyOf( vevent, VCDTstartProp ) ) ) {
01020 anEvent->setDtStart( anEvent->dtEnd() );
01021 }
01022 if ( !( vo = isAPropertyOf( vevent, VCDTendProp ) ) ) {
01023 anEvent->setDtEnd( anEvent->dtStart() );
01024 }
01025
01027
01028
01029 if ( ( vo = isAPropertyOf( vevent, VCRRuleProp ) ) != 0 ) {
01030 QString tmpStr = ( s = fakeCString( vObjectUStringZValue( vo ) ) );
01031 deleteStr( s );
01032 tmpStr.simplified();
01033 tmpStr = tmpStr.toUpper();
01034
01035
01036 int typelen = 1;
01037 uint type = Recurrence::rNone;
01038 if ( tmpStr.left(1) == "D" ) {
01039 type = Recurrence::rDaily;
01040 } else if ( tmpStr.left(1) == "W" ) {
01041 type = Recurrence::rWeekly;
01042 } else {
01043 typelen = 2;
01044 if ( tmpStr.left(2) == "MP" ) {
01045 type = Recurrence::rMonthlyPos;
01046 } else if ( tmpStr.left(2) == "MD" ) {
01047 type = Recurrence::rMonthlyDay;
01048 } else if ( tmpStr.left(2) == "YM" ) {
01049 type = Recurrence::rYearlyMonth;
01050 } else if ( tmpStr.left(2) == "YD" ) {
01051 type = Recurrence::rYearlyDay;
01052 }
01053 }
01054
01055 if ( type != Recurrence::rNone ) {
01056
01057
01058 int index = tmpStr.indexOf( ' ' );
01059 int last = tmpStr.lastIndexOf( ' ' ) + 1;
01060 int rFreq = tmpStr.mid( typelen, ( index - 1 ) ).toInt();
01061 ++index;
01062
01063
01064 switch ( type ) {
01065 case Recurrence::rDaily:
01066 anEvent->recurrence()->setDaily(rFreq);
01067 break;
01068
01069 case Recurrence::rWeekly:
01070 {
01071 QBitArray qba(7);
01072 QString dayStr;
01073 if ( index == last ) {
01074
01075 qba.setBit( anEvent->dtStart().date().dayOfWeek() - 1 );
01076 } else {
01077
01078 while ( index < last ) {
01079 dayStr = tmpStr.mid( index, 3 );
01080 int dayNum = numFromDay( dayStr );
01081 if ( dayNum >= 0 ) {
01082 qba.setBit( dayNum );
01083 }
01084 index += 3;
01085 }
01086 }
01087 anEvent->recurrence()->setWeekly( rFreq, qba );
01088 break;
01089 }
01090
01091 case Recurrence::rMonthlyPos:
01092 {
01093 anEvent->recurrence()->setMonthly( rFreq );
01094
01095 QBitArray qba(7);
01096 short tmpPos;
01097 if ( index == last ) {
01098
01099 tmpPos = anEvent->dtStart().date().day() / 7 + 1;
01100 if ( tmpPos == 5 ) {
01101 tmpPos = -1;
01102 }
01103 qba.setBit( anEvent->dtStart().date().dayOfWeek() - 1 );
01104 anEvent->recurrence()->addMonthlyPos( tmpPos, qba );
01105 } else {
01106
01107 while ( index < last ) {
01108 tmpPos = tmpStr.mid( index, 1 ).toShort();
01109 index += 1;
01110 if ( tmpStr.mid( index, 1 ) == "-" ) {
01111
01112 tmpPos = 0 - tmpPos;
01113 }
01114 index += 2;
01115 while ( numFromDay( tmpStr.mid( index, 3 ) ) >= 0 ) {
01116 int dayNum = numFromDay( tmpStr.mid( index, 3 ) );
01117 qba.setBit( dayNum );
01118 index += 3;
01119 }
01120 anEvent->recurrence()->addMonthlyPos( tmpPos, qba );
01121 qba.detach();
01122 qba.fill( false );
01123 }
01124 }
01125 break;
01126 }
01127
01128 case Recurrence::rMonthlyDay:
01129 anEvent->recurrence()->setMonthly( rFreq );
01130 if( index == last ) {
01131
01132 short tmpDay = anEvent->dtStart().date().day();
01133 anEvent->recurrence()->addMonthlyDate( tmpDay );
01134 } else {
01135
01136 while ( index < last ) {
01137 int index2 = tmpStr.indexOf( ' ', index );
01138 short tmpDay = tmpStr.mid( index, ( index2 - index ) ).toShort();
01139 index = index2 - 1;
01140 if ( tmpStr.mid( index, 1 ) == "-" ) {
01141 tmpDay = 0 - tmpDay;
01142 }
01143 index += 2;
01144 anEvent->recurrence()->addMonthlyDate( tmpDay );
01145 }
01146 }
01147 break;
01148
01149 case Recurrence::rYearlyMonth:
01150 anEvent->recurrence()->setYearly( rFreq );
01151
01152 if ( index == last ) {
01153
01154 short tmpMonth = anEvent->dtStart().date().month();
01155 anEvent->recurrence()->addYearlyMonth( tmpMonth );
01156 } else {
01157
01158 while ( index < last ) {
01159 int index2 = tmpStr.indexOf( ' ', index );
01160 short tmpMonth = tmpStr.mid( index, ( index2 - index ) ).toShort();
01161 index = index2 + 1;
01162 anEvent->recurrence()->addYearlyMonth( tmpMonth );
01163 }
01164 }
01165 break;
01166
01167 case Recurrence::rYearlyDay:
01168 anEvent->recurrence()->setYearly( rFreq );
01169
01170 if ( index == last ) {
01171
01172 short tmpDay = anEvent->dtStart().date().dayOfYear();
01173 anEvent->recurrence()->addYearlyDay( tmpDay );
01174 } else {
01175
01176 while ( index < last ) {
01177 int index2 = tmpStr.indexOf( ' ', index );
01178 short tmpDay = tmpStr.mid( index, ( index2 - index ) ).toShort();
01179 index = index2 + 1;
01180 anEvent->recurrence()->addYearlyDay( tmpDay );
01181 }
01182 }
01183 break;
01184
01185 default:
01186 break;
01187 }
01188
01189
01190 index = last;
01191 if ( tmpStr.mid( index, 1 ) == "#" ) {
01192
01193 index++;
01194 int rDuration = tmpStr.mid( index, tmpStr.length() - index ).toInt();
01195 if ( rDuration > 0 ) {
01196 anEvent->recurrence()->setDuration( rDuration );
01197 }
01198 } else if ( tmpStr.indexOf( 'T', index ) != -1 ) {
01199 KDateTime rEndDate = ISOToKDateTime( tmpStr.mid( index, tmpStr.length() - index ) );
01200 rEndDate.setDateOnly( true );
01201 anEvent->recurrence()->setEndDateTime( rEndDate );
01202 }
01203
01204
01205 } else {
01206 kDebug() << "we don't understand this type of recurrence!";
01207 }
01208 }
01209
01210
01211 if ( ( vo = isAPropertyOf( vevent, VCExpDateProp ) ) != 0 ) {
01212 s = fakeCString( vObjectUStringZValue( vo ) );
01213 QStringList exDates = QString::fromLocal8Bit( s ).split( ',' );
01214 QStringList::ConstIterator it;
01215 for ( it = exDates.constBegin(); it != exDates.constEnd(); ++it ) {
01216 anEvent->recurrence()->addExDate( ISOToQDate(*it) );
01217 }
01218 deleteStr( s );
01219 }
01220
01221
01222 if ( ( vo = isAPropertyOf( vevent, VCSummaryProp ) ) ) {
01223 s = fakeCString( vObjectUStringZValue( vo ) );
01224 anEvent->setSummary( QString::fromLocal8Bit( s ), Qt::mightBeRichText( s ) );
01225 deleteStr( s );
01226 }
01227
01228
01229 if ( ( vo = isAPropertyOf( vevent, VCDescriptionProp ) ) != 0 ) {
01230 s = fakeCString( vObjectUStringZValue( vo ) );
01231 bool isRich = Qt::mightBeRichText( s );
01232 if ( !anEvent->description().isEmpty() ) {
01233 anEvent->setDescription(
01234 anEvent->description() + '\n' + QString::fromLocal8Bit( s ), isRich );
01235 } else {
01236 anEvent->setDescription( QString::fromLocal8Bit( s ), isRich );
01237 }
01238 deleteStr( s );
01239 }
01240
01241
01242 if ( ( vo = isAPropertyOf( vevent, VCLocationProp ) ) != 0 ) {
01243 s = fakeCString( vObjectUStringZValue( vo ) );
01244 anEvent->setLocation( QString::fromLocal8Bit( s ), Qt::mightBeRichText( s ) );
01245 deleteStr( s );
01246 }
01247
01248
01249
01250 if ( anEvent->summary().isEmpty() && !( anEvent->description().isEmpty() ) ) {
01251 QString tmpStr = anEvent->description().simplified();
01252 anEvent->setDescription( "" );
01253 anEvent->setSummary( tmpStr );
01254 }
01255
01256 #if 0
01257
01258 if ( ( vo = isAPropertyOf( vevent, VCStatusProp ) ) != 0 ) {
01259 QString tmpStr( s = fakeCString( vObjectUStringZValue( vo ) ) );
01260 deleteStr( s );
01261
01262
01263 } else {
01264
01265 }
01266 #endif
01267
01268
01269 Incidence::Secrecy secrecy = Incidence::SecrecyPublic;
01270 if ( ( vo = isAPropertyOf( vevent, VCClassProp ) ) != 0 ) {
01271 s = fakeCString( vObjectUStringZValue( vo ) );
01272 if ( s && strcmp( s, "PRIVATE" ) == 0 ) {
01273 secrecy = Incidence::SecrecyPrivate;
01274 } else if ( s && strcmp( s, "CONFIDENTIAL" ) == 0 ) {
01275 secrecy = Incidence::SecrecyConfidential;
01276 }
01277 deleteStr( s );
01278 }
01279 anEvent->setSecrecy( secrecy );
01280
01281
01282 if ( ( vo = isAPropertyOf( vevent, VCCategoriesProp ) ) != 0 ) {
01283 s = fakeCString( vObjectUStringZValue( vo ) );
01284 QString categories = QString::fromLocal8Bit( s );
01285 deleteStr( s );
01286 QStringList tmpStrList = categories.split( ',' );
01287 anEvent->setCategories( tmpStrList );
01288 }
01289
01290
01291 initPropIterator( &voi, vevent );
01292 while ( moreIteration( &voi ) ) {
01293 vo = nextVObject( &voi );
01294 if ( strcmp( vObjectName( vo ), VCAttachProp ) == 0 ) {
01295 s = fakeCString( vObjectUStringZValue( vo ) );
01296 anEvent->addAttachment( new Attachment( QString( s ) ) );
01297 deleteStr( s );
01298 }
01299 }
01300
01301
01302 if ( ( vo = isAPropertyOf( vevent, VCResourcesProp ) ) != 0 ) {
01303 QString resources = ( s = fakeCString( vObjectUStringZValue( vo ) ) );
01304 deleteStr( s );
01305 QStringList tmpStrList = resources.split( ';' );
01306 anEvent->setResources( tmpStrList );
01307 }
01308
01309
01310 if ( ( vo = isAPropertyOf( vevent, VCDAlarmProp ) ) ) {
01311 Alarm *alarm = anEvent->newAlarm();
01312 VObject *a;
01313 if ( ( a = isAPropertyOf( vo, VCRunTimeProp ) ) ) {
01314 alarm->setTime( ISOToKDateTime( s = fakeCString( vObjectUStringZValue( a ) ) ) );
01315 deleteStr( s );
01316 }
01317 alarm->setEnabled( true );
01318 if ( ( vo = isAPropertyOf( vevent, VCPAlarmProp ) ) ) {
01319 if ( ( a = isAPropertyOf( vo, VCProcedureNameProp ) ) ) {
01320 s = fakeCString( vObjectUStringZValue( a ) );
01321 alarm->setProcedureAlarm( QFile::decodeName( s ) );
01322 deleteStr( s );
01323 }
01324 }
01325 if ( ( vo = isAPropertyOf( vevent, VCAAlarmProp ) ) ) {
01326 if ( ( a = isAPropertyOf( vo, VCAudioContentProp ) ) ) {
01327 s = fakeCString( vObjectUStringZValue( a ) );
01328 alarm->setAudioAlarm( QFile::decodeName( s ) );
01329 deleteStr( s );
01330 }
01331 }
01332 }
01333
01334
01335 if ( ( vo = isAPropertyOf( vevent, VCPriorityProp ) ) ) {
01336 s = fakeCString( vObjectUStringZValue( vo ) );
01337 if ( s ) {
01338 anEvent->setPriority( atoi( s ) );
01339 deleteStr( s );
01340 }
01341 }
01342
01343
01344 if ( ( vo = isAPropertyOf( vevent, VCTranspProp ) ) != 0 ) {
01345 s = fakeCString( vObjectUStringZValue( vo ) );
01346 if ( s ) {
01347 int i = atoi( s );
01348 anEvent->setTransparency( i == 1 ? Event::Transparent : Event::Opaque );
01349 deleteStr( s );
01350 }
01351 }
01352
01353
01354 if ( ( vo = isAPropertyOf( vevent, VCRelatedToProp ) ) != 0 ) {
01355 anEvent->setRelatedToUid( s = fakeCString( vObjectUStringZValue( vo ) ) );
01356 deleteStr( s );
01357 d->mEventsRelate.append( anEvent );
01358 }
01359
01360
01361 if ( ( vo = isAPropertyOf( vevent, KPilotIdProp ) ) ) {
01362 anEvent->setNonKDECustomProperty(
01363 KPilotIdProp, QString::fromLocal8Bit( s = fakeCString( vObjectUStringZValue( vo ) ) ) );
01364 deleteStr( s );
01365 if ( ( vo = isAPropertyOf( vevent, KPilotStatusProp ) ) ) {
01366 anEvent->setNonKDECustomProperty(
01367 KPilotStatusProp, QString::fromLocal8Bit( s = fakeCString( vObjectUStringZValue( vo ) ) ) );
01368 deleteStr( s );
01369 } else {
01370 anEvent->setNonKDECustomProperty( KPilotStatusProp, QString::number( SYNCMOD ) );
01371 }
01372 }
01373
01374 return anEvent;
01375 }
01376
01377 QString VCalFormat::qDateToISO( const QDate &qd )
01378 {
01379 QString tmpStr;
01380
01381 if ( !qd.isValid() ) {
01382 return QString();
01383 }
01384
01385 tmpStr.sprintf( "%.2d%.2d%.2d", qd.year(), qd.month(), qd.day() );
01386 return tmpStr;
01387
01388 }
01389
01390 QString VCalFormat::kDateTimeToISO( const KDateTime &dt, bool zulu )
01391 {
01392 QString tmpStr;
01393
01394 if ( !dt.isValid() ) {
01395 return QString();
01396 }
01397
01398 QDateTime tmpDT;
01399 if ( zulu ) {
01400 tmpDT = dt.toUtc().dateTime();
01401 } else {
01402 tmpDT = dt.toTimeSpec( d->mCalendar->timeSpec() ).dateTime();
01403 }
01404 tmpStr.sprintf( "%.2d%.2d%.2dT%.2d%.2d%.2d",
01405 tmpDT.date().year(), tmpDT.date().month(),
01406 tmpDT.date().day(), tmpDT.time().hour(),
01407 tmpDT.time().minute(), tmpDT.time().second() );
01408 if ( zulu ) {
01409 tmpStr += 'Z';
01410 }
01411 return tmpStr;
01412 }
01413
01414 KDateTime VCalFormat::ISOToKDateTime( const QString &dtStr )
01415 {
01416 QDate tmpDate;
01417 QTime tmpTime;
01418 QString tmpStr;
01419 int year, month, day, hour, minute, second;
01420
01421 tmpStr = dtStr;
01422 year = tmpStr.left( 4 ).toInt();
01423 month = tmpStr.mid( 4, 2 ).toInt();
01424 day = tmpStr.mid( 6, 2 ).toInt();
01425 hour = tmpStr.mid( 9, 2 ).toInt();
01426 minute = tmpStr.mid( 11, 2 ).toInt();
01427 second = tmpStr.mid( 13, 2 ).toInt();
01428 tmpDate.setYMD( year, month, day );
01429 tmpTime.setHMS( hour, minute, second );
01430
01431 if ( tmpDate.isValid() && tmpTime.isValid() ) {
01432
01433 if ( dtStr.at( dtStr.length() - 1 ) == 'Z' ) {
01434 return KDateTime( tmpDate, tmpTime, KDateTime::UTC );
01435 } else {
01436 return KDateTime( tmpDate, tmpTime, d->mCalendar->timeSpec() );
01437 }
01438 } else {
01439 return KDateTime();
01440 }
01441 }
01442
01443 QDate VCalFormat::ISOToQDate( const QString &dateStr )
01444 {
01445 int year, month, day;
01446
01447 year = dateStr.left( 4 ).toInt();
01448 month = dateStr.mid( 4, 2 ).toInt();
01449 day = dateStr.mid( 6, 2 ).toInt();
01450
01451 return QDate( year, month, day );
01452 }
01453
01454
01455
01456
01457 void VCalFormat::populate( VObject *vcal )
01458 {
01459
01460
01461
01462 VObjectIterator i;
01463 VObject *curVO, *curVOProp;
01464 Event *anEvent;
01465
01466 if ( ( curVO = isAPropertyOf( vcal, ICMethodProp ) ) != 0 ) {
01467 char *methodType = 0;
01468 methodType = fakeCString( vObjectUStringZValue( curVO ) );
01469 kDebug() << "This calendar is an iTIP transaction of type '"
01470 << methodType << "'";
01471 deleteStr( methodType );
01472 }
01473
01474
01475 if ( ( curVO = isAPropertyOf( vcal, VCProdIdProp ) ) != 0 ) {
01476 char *s = fakeCString( vObjectUStringZValue( curVO ) );
01477 if ( !s || strcmp( productId().toLocal8Bit(), s ) != 0 ) {
01478 kDebug() << "This vCalendar file was not created by KOrganizer or"
01479 << "any other product we support. Loading anyway...";
01480 }
01481 setLoadedProductId( s );
01482 deleteStr( s );
01483 }
01484
01485
01486 if ( ( curVO = isAPropertyOf( vcal, VCVersionProp ) ) != 0 ) {
01487 char *s = fakeCString( vObjectUStringZValue( curVO ) );
01488 if ( !s || strcmp( _VCAL_VERSION, s ) != 0 ) {
01489 kDebug() << "This vCalendar file has version" << s
01490 << "We only support" << _VCAL_VERSION;
01491 }
01492 deleteStr( s );
01493 }
01494
01495 #if 0
01496
01497 if ( ( curVO = isAPropertyOf( vcal, VCTimeZoneProp ) ) != 0 ) {
01498 char *s = fakeCString( vObjectUStringZValue( curVO ) );
01499 d->mCalendar->setTimeZone( s );
01500 deleteStr( s );
01501 }
01502 #endif
01503
01504
01505 d->mEventsRelate.clear();
01506 d->mTodosRelate.clear();
01507
01508 initPropIterator( &i, vcal );
01509
01510
01511 while ( moreIteration( &i ) ) {
01512 curVO = nextVObject( &i );
01513
01514
01515
01516
01517 if ( strcmp( vObjectName( curVO ), VCEventProp ) == 0 ) {
01518
01519 if ( ( curVOProp = isAPropertyOf( curVO, KPilotStatusProp ) ) != 0 ) {
01520 char *s;
01521 s = fakeCString( vObjectUStringZValue( curVOProp ) );
01522
01523 if ( s ) {
01524 if ( atoi( s ) == SYNCDEL ) {
01525 deleteStr( s );
01526 kDebug() << "skipping pilot-deleted event";
01527 goto SKIP;
01528 }
01529 deleteStr( s );
01530 }
01531 }
01532
01533
01534
01535
01536 if ( ( curVOProp = isAPropertyOf( curVO, VCUniqueStringProp ) ) != 0 ) {
01537 char *s = fakeCString( vObjectUStringZValue( curVOProp ) );
01538 QString tmpStr( s );
01539 deleteStr( s );
01540
01541 if ( d->mCalendar->incidence( tmpStr ) ) {
01542 goto SKIP;
01543 }
01544 }
01545
01546 if ( ( !( curVOProp = isAPropertyOf( curVO, VCDTstartProp ) ) ) &&
01547 ( !( curVOProp = isAPropertyOf( curVO, VCDTendProp ) ) ) ) {
01548 kDebug() << "found a VEvent with no DTSTART and no DTEND! Skipping...";
01549 goto SKIP;
01550 }
01551
01552 anEvent = VEventToEvent( curVO );
01553
01554
01555 if ( anEvent ) {
01556 if ( anEvent->dtStart().isValid() && anEvent->dtEnd().isValid() ) {
01557 d->mCalendar->addEvent( anEvent );
01558 }
01559 } else {
01560
01561 goto SKIP;
01562 }
01563 } else if ( strcmp( vObjectName( curVO ), VCTodoProp ) == 0 ) {
01564 Todo *aTodo = VTodoToEvent( curVO );
01565
01566 Todo *old = d->mCalendar->todo( aTodo->uid() );
01567 if ( old ) {
01568 d->mCalendar->deleteTodo( old );
01569 d->mTodosRelate.removeAll( old );
01570 }
01571
01572 d->mCalendar->addTodo( aTodo );
01573 } else if ( ( strcmp( vObjectName( curVO ), VCVersionProp ) == 0 ) ||
01574 ( strcmp( vObjectName( curVO ), VCProdIdProp ) == 0 ) ||
01575 ( strcmp( vObjectName( curVO ), VCTimeZoneProp ) == 0 ) ) {
01576
01577
01578 ;
01579 } else {
01580 kDebug() << "Ignoring unknown vObject \"" << vObjectName(curVO) << "\"";
01581 }
01582 SKIP:
01583 ;
01584 }
01585
01586
01587 Event::List::ConstIterator eIt;
01588 for ( eIt = d->mEventsRelate.constBegin(); eIt != d->mEventsRelate.constEnd(); ++eIt ) {
01589 (*eIt)->setRelatedTo( d->mCalendar->incidence( (*eIt)->relatedToUid() ) );
01590 }
01591 Todo::List::ConstIterator tIt;
01592 for ( tIt = d->mTodosRelate.constBegin(); tIt != d->mTodosRelate.constEnd(); ++tIt ) {
01593 (*tIt)->setRelatedTo( d->mCalendar->incidence( (*tIt)->relatedToUid() ) );
01594 }
01595 }
01596
01597 const char *VCalFormat::dayFromNum( int day )
01598 {
01599 const char *days[7] = { "MO ", "TU ", "WE ", "TH ", "FR ", "SA ", "SU " };
01600
01601 return days[day];
01602 }
01603
01604 int VCalFormat::numFromDay( const QString &day )
01605 {
01606 if ( day == "MO " ) {
01607 return 0;
01608 }
01609 if ( day == "TU " ) {
01610 return 1;
01611 }
01612 if ( day == "WE " ) {
01613 return 2;
01614 }
01615 if ( day == "TH " ) {
01616 return 3;
01617 }
01618 if ( day == "FR " ) {
01619 return 4;
01620 }
01621 if ( day == "SA " ) {
01622 return 5;
01623 }
01624 if ( day == "SU " ) {
01625 return 6;
01626 }
01627
01628 return -1;
01629 }
01630
01631 Attendee::PartStat VCalFormat::readStatus( const char *s ) const
01632 {
01633 QString statStr = s;
01634 statStr = statStr.toUpper();
01635 Attendee::PartStat status;
01636
01637 if ( statStr == "X-ACTION" ) {
01638 status = Attendee::NeedsAction;
01639 } else if ( statStr == "NEEDS ACTION" ) {
01640 status = Attendee::NeedsAction;
01641 } else if ( statStr == "ACCEPTED" ) {
01642 status = Attendee::Accepted;
01643 } else if ( statStr == "SENT" ) {
01644 status = Attendee::NeedsAction;
01645 } else if ( statStr == "TENTATIVE" ) {
01646 status = Attendee::Tentative;
01647 } else if ( statStr == "CONFIRMED" ) {
01648 status = Attendee::Accepted;
01649 } else if ( statStr == "DECLINED" ) {
01650 status = Attendee::Declined;
01651 } else if ( statStr == "COMPLETED" ) {
01652 status = Attendee::Completed;
01653 } else if ( statStr == "DELEGATED" ) {
01654 status = Attendee::Delegated;
01655 } else {
01656 kDebug() << "error setting attendee mStatus, unknown mStatus!";
01657 status = Attendee::NeedsAction;
01658 }
01659
01660 return status;
01661 }
01662
01663 QByteArray VCalFormat::writeStatus( Attendee::PartStat status ) const
01664 {
01665 switch( status ) {
01666 default:
01667 case Attendee::NeedsAction:
01668 return "NEEDS ACTION";
01669 break;
01670 case Attendee::Accepted:
01671 return "ACCEPTED";
01672 break;
01673 case Attendee::Declined:
01674 return "DECLINED";
01675 break;
01676 case Attendee::Tentative:
01677 return "TENTATIVE";
01678 break;
01679 case Attendee::Delegated:
01680 return "DELEGATED";
01681 break;
01682 case Attendee::Completed:
01683 return "COMPLETED";
01684 break;
01685 case Attendee::InProcess:
01686 return "NEEDS ACTION";
01687 break;
01688 }
01689 }