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