41 #include "icaltimezones.h"
43 #include "versit/vcc.h"
44 #include "versit/vobject.h"
49 #include <QtCore/QBitArray>
50 #include <QtCore/QFile>
51 #include <QtGui/QTextDocument>
53 using namespace KCalCore;
61 void removeAllVCal( QVector< QSharedPointer<K> > &c,
const QSharedPointer<K> &x )
63 Q_ASSERT( c.count( x ) == 1 );
64 c.remove( c.indexOf( x ) );
67 class KCalCore::VCalFormat::Private
73 QSet<QByteArray> mManuallyWrittenExtensionFields;
79 #if defined(KCALCORE_FOR_SYMBIAN)
80 d->mManuallyWrittenExtensionFields << VCRecurrenceIdProp;
81 d->mManuallyWrittenExtensionFields << EPOCAgendaEntryTypeProp;
83 d->mManuallyWrittenExtensionFields << KPilotIdProp;
84 d->mManuallyWrittenExtensionFields << KPilotStatusProp;
94 d->mCalendar = calendar;
102 vcal = Parse_MIME_FromFileName( const_cast<char *>( QFile::encodeName( fileName ).data() ) );
112 QString savedTimeZoneId = d->mCalendar->timeZoneId();
114 d->mCalendar->setTimeZoneId(savedTimeZoneId);
117 cleanVObjects( vcal );
125 d->mCalendar = calendar;
132 vcal = newVObject( VCCalProp );
135 addPropValue( vcal, VCProdIdProp,
productId().toLatin1() );
136 addPropValue( vcal, VCVersionProp, _VCAL_VERSION );
139 Todo::List todoList = d->mCalendar->rawTodos();
140 Todo::List::ConstIterator it;
141 for ( it = todoList.constBegin(); it != todoList.constEnd(); ++it ) {
142 if ( (*it)->dtStart().timeZone().name().mid( 0, 4 ) ==
"VCAL" ) {
144 if ( zone.isValid() ) {
146 addPropValue( vcal, VCTimeZoneProp,
parseTZ( timezone ).toLocal8Bit() );
148 while ( !dst.isEmpty() ) {
149 addPropValue( vcal, VCDayLightProp, dst.toLocal8Bit() );
155 addVObjectProp( vcal, vo );
159 Event::List::ConstIterator it2;
160 for ( it2 = events.constBegin(); it2 != events.constEnd(); ++it2 ) {
161 if ( (*it2)->dtStart().timeZone().name().mid( 0, 4 ) ==
"VCAL" ) {
163 if ( zone.isValid() ) {
165 addPropValue( vcal, VCTimeZoneProp,
parseTZ( timezone ).toLocal8Bit() );
167 while ( !dst.isEmpty() ) {
168 addPropValue( vcal, VCDayLightProp, dst.toLocal8Bit() );
174 addVObjectProp( vcal, vo );
176 writeVObjectToFile( QFile::encodeName( fileName ).data(), vcal );
177 cleanVObjects( vcal );
180 if ( QFile::exists( fileName ) ) {
190 bool deleted,
const QString ¬ebook )
192 return fromRawString( calendar,
string.toUtf8(), deleted, notebook );
196 bool deleted,
const QString ¬ebook )
198 d->mCalendar = calendar;
200 if ( !
string.size() ) {
204 VObject *vcal = Parse_MIME(
string.data(),
string.size() );
210 initPropIterator( &i, vcal );
213 QString savedTimeZoneId = d->mCalendar->timeZoneId();
214 populate( vcal, deleted, notebook );
215 d->mCalendar->setTimeZoneId(savedTimeZoneId);
218 cleanVObjects( vcal );
225 const QString ¬ebook,
bool deleted )
228 d->mCalendar = calendar;
233 VObject *vcal = newVObject( VCCalProp );
236 addPropValue( vcal, VCVersionProp, _VCAL_VERSION );
239 Todo::List todoList = deleted ? d->mCalendar->deletedTodos() : d->mCalendar->rawTodos();
240 Todo::List::ConstIterator it;
241 for ( it = todoList.constBegin(); it != todoList.constEnd(); ++it ) {
242 if ( !deleted || !d->mCalendar->todo( (*it)->uid(), (*it)->recurrenceId() ) ) {
244 if ( notebook.isEmpty() ||
245 ( !calendar->notebook(*it).isEmpty() &&
246 notebook.endsWith( calendar->notebook( *it ) ) ) ) {
247 if ( (*it)->dtStart().timeZone().name().mid( 0, 4 ) ==
"VCAL" ) {
249 if ( zone.isValid() ) {
251 addPropValue( vcal, VCTimeZoneProp,
parseTZ( timezone ).toUtf8() );
253 while ( !dst.isEmpty() ) {
254 addPropValue( vcal, VCDayLightProp, dst.toUtf8() );
260 addVObjectProp( vcal, vo );
266 Event::List events = deleted ? d->mCalendar->deletedEvents() : d->mCalendar->rawEvents();
267 Event::List::ConstIterator it2;
268 for ( it2 = events.constBegin(); it2 != events.constEnd(); ++it2 ) {
269 if ( !deleted || !d->mCalendar->event( (*it2)->uid(), (*it2)->recurrenceId() ) ) {
271 if ( notebook.isEmpty() ||
272 ( !calendar->notebook( *it2 ).isEmpty() &&
273 notebook.endsWith( calendar->notebook( *it2 ) ) ) ) {
274 if ( (*it2)->dtStart().timeZone().name().mid( 0, 4 ) ==
"VCAL" ) {
276 if ( zone.isValid() ) {
278 addPropValue( vcal, VCTimeZoneProp,
parseTZ( timezone ).toUtf8() );
280 while ( !dst.isEmpty() ) {
281 addPropValue( vcal, VCDayLightProp, dst.toUtf8() );
287 addVObjectProp( vcal, vo );
292 char *buf = writeMemVObject( 0, 0, vcal );
294 QString result( QString::fromUtf8(buf) );
298 cleanVObject( vcal );
308 vtodo = newVObject( VCTodoProp );
311 if ( anEvent->hasDueDate() ) {
313 addPropValue( vtodo, VCDueProp, tmpStr.toUtf8() );
317 if ( anEvent->hasStartDate() ) {
318 tmpStr =
kDateTimeToISO( anEvent->dtStart(), !anEvent->allDay() );
319 addPropValue( vtodo, VCDTstartProp, tmpStr.toUtf8() );
324 addPropValue( vtodo, VCDCreatedProp, tmpStr.toUtf8() );
327 addPropValue( vtodo, VCUniqueStringProp,
328 anEvent->uid().toUtf8() );
331 tmpStr.sprintf(
"%i", anEvent->revision() );
332 addPropValue( vtodo, VCSequenceProp, tmpStr.toUtf8() );
336 addPropValue( vtodo, VCLastModifiedProp, tmpStr.toUtf8() );
340 if ( !anEvent->organizer()->email().isEmpty() ) {
341 tmpStr =
"MAILTO:" + anEvent->organizer()->email();
342 addPropValue( vtodo, ICOrganizerProp, tmpStr.toUtf8() );
346 if ( anEvent->attendeeCount() > 0 ) {
347 Attendee::List::ConstIterator it;
349 for ( it = anEvent->attendees().constBegin(); it != anEvent->attendees().constEnd();
352 if ( !curAttendee->email().isEmpty() && !curAttendee->name().isEmpty() ) {
353 tmpStr =
"MAILTO:" + curAttendee->name() +
" <" + curAttendee->email() +
'>';
354 }
else if ( curAttendee->name().isEmpty() && curAttendee->email().isEmpty() ) {
356 kDebug() <<
"warning! this Event has an attendee w/o name or email!";
357 }
else if ( curAttendee->name().isEmpty() ) {
358 tmpStr =
"MAILTO: " + curAttendee->email();
360 tmpStr =
"MAILTO: " + curAttendee->name();
362 VObject *aProp = addPropValue( vtodo, VCAttendeeProp, tmpStr.toUtf8() );
363 addPropValue( aProp, VCRSVPProp, curAttendee->RSVP() ?
"TRUE" :
"FALSE" );
364 addPropValue( aProp, VCStatusProp,
writeStatus( curAttendee->status() ) );
369 const Recurrence *recur = anEvent->recurrence();
371 bool validRecur =
true;
374 case Recurrence::rDaily:
375 tmpStr.sprintf(
"D%i ", recur->
frequency() );
377 case Recurrence::rWeekly:
378 tmpStr.sprintf(
"W%i ", recur->
frequency() );
379 for (
int i = 0; i < 7; ++i ) {
380 QBitArray days ( recur->
days() );
381 if ( days.testBit(i) ) {
386 case Recurrence::rMonthlyPos:
388 tmpStr.sprintf(
"MP%i ", recur->
frequency() );
390 QList<RecurrenceRule::WDayPos> tmpPositions = recur->
monthPositions();
391 for ( QList<RecurrenceRule::WDayPos>::ConstIterator posit = tmpPositions.constBegin();
392 posit != tmpPositions.constEnd(); ++posit ) {
393 int pos = (*posit).pos();
394 tmpStr2.sprintf(
"%i", ( pos > 0 ) ? pos : (-pos) );
405 case Recurrence::rMonthlyDay:
407 tmpStr.sprintf(
"MD%i ", recur->
frequency() );
409 const QList<int> tmpDays = recur->
monthDays();
410 for ( QList<int>::ConstIterator tmpDay = tmpDays.constBegin();
411 tmpDay != tmpDays.constEnd(); ++tmpDay ) {
412 tmpStr2.sprintf(
"%i ", *tmpDay );
417 case Recurrence::rYearlyMonth:
419 tmpStr.sprintf(
"YM%i ", recur->
frequency() );
422 const QList<int> months = recur->
yearMonths();
423 for ( QList<int>::ConstIterator mit = months.constBegin();
424 mit != months.constEnd(); ++mit ) {
425 tmpStr2.sprintf(
"%i ", *mit );
430 case Recurrence::rYearlyDay:
432 tmpStr.sprintf(
"YD%i ", recur->
frequency() );
434 const QList<int> tmpDays = recur->
yearDays();
435 for ( QList<int>::ConstIterator tmpDay = tmpDays.begin();
436 tmpDay != tmpDays.end(); ++tmpDay ) {
437 tmpStr2.sprintf(
"%i ", *tmpDay );
444 kDebug() <<
"ERROR, it should never get here in eventToVTodo!";
450 tmpStr2.sprintf(
"#%i", recur->
duration() );
452 }
else if ( recur->
duration() == -1 ) {
460 addPropValue( vtodo, VCRRuleProp, tmpStr.toUtf8() );
466 DateList dateList = recur->exDates();
467 DateList::ConstIterator id;
470 for (
id = dateList.constBegin();
id != dateList.constEnd(); ++id ) {
474 if ( !tmpStr2.isEmpty() ) {
475 tmpStr2.truncate( tmpStr2.length() - 1 );
476 addPropValue( vtodo, VCExpDateProp, tmpStr2.toUtf8() );
480 DateTimeList::ConstIterator idt;
483 for ( idt = dateTimeList.constBegin(); idt != dateTimeList.constEnd(); ++idt ) {
487 if ( !tmpStr2.isEmpty() ) {
488 tmpStr2.truncate( tmpStr2.length() - 1 );
489 addPropValue( vtodo, VCExpDateProp, tmpStr2.toUtf8() );
493 if ( !anEvent->description().isEmpty() ) {
494 QByteArray in = anEvent->description().toUtf8();
496 KCodecs::quotedPrintableEncode( in, out,
true );
498 VObject *d = addPropValue( vtodo, VCDescriptionProp, out );
499 addPropValue( d, VCEncodingProp, VCQuotedPrintableProp );
500 addPropValue( d, VCCharSetProp, VCUtf8Prop );
502 addPropValue( vtodo, VCDescriptionProp, in );
507 if ( !anEvent->summary().isEmpty() ) {
508 QByteArray in = anEvent->summary().toUtf8();
510 KCodecs::quotedPrintableEncode( in, out,
true );
512 VObject *d = addPropValue( vtodo, VCSummaryProp, out );
513 addPropValue( d, VCEncodingProp, VCQuotedPrintableProp );
514 addPropValue( d, VCCharSetProp, VCUtf8Prop );
516 addPropValue( vtodo, VCSummaryProp, in );
521 if ( !anEvent->location().isEmpty() ) {
522 QByteArray in = anEvent->location().toUtf8();
524 KCodecs::quotedPrintableEncode( in, out,
true );
526 VObject *d = addPropValue( vtodo, VCLocationProp, out );
527 addPropValue( d, VCEncodingProp, VCQuotedPrintableProp );
528 addPropValue( d, VCCharSetProp, VCUtf8Prop );
530 addPropValue( vtodo, VCLocationProp, in );
536 addPropValue( vtodo, VCStatusProp, anEvent->isCompleted() ?
"COMPLETED" :
"NEEDS ACTION" );
539 if ( anEvent->hasCompletedDate() ) {
541 addPropValue( vtodo, VCCompletedProp, tmpStr.toUtf8() );
545 tmpStr.sprintf(
"%i", anEvent->priority() );
546 addPropValue( vtodo, VCPriorityProp, tmpStr.toUtf8() );
549 if ( !anEvent->relatedTo().isEmpty() ) {
550 addPropValue( vtodo, VCRelatedToProp,
551 anEvent->relatedTo().toUtf8() );
555 const char *text = 0;
556 switch ( anEvent->secrecy() ) {
564 text =
"CONFIDENTIAL";
568 addPropValue( vtodo, VCClassProp, text );
572 const QStringList tmpStrList = anEvent->categories();
575 QStringList::const_iterator its;
576 for ( its = tmpStrList.constBegin(); its != tmpStrList.constEnd(); ++its ) {
578 if ( catStr[0] ==
' ' ) {
579 tmpStr += catStr.mid( 1 );
588 if ( !tmpStr.isEmpty() ) {
589 tmpStr.truncate( tmpStr.length() - 1 );
590 addPropValue( vtodo, VCCategoriesProp, tmpStr.toUtf8() );
594 Alarm::List::ConstIterator it;
595 for ( it = anEvent->alarms().constBegin(); it != anEvent->alarms().constEnd(); ++it ) {
597 if ( alarm->enabled() ) {
600 a = addProp( vtodo, VCDAlarmProp );
602 addPropValue( a, VCRunTimeProp, tmpStr.toUtf8() );
603 addPropValue( a, VCRepeatCountProp,
"1" );
604 if ( alarm->text().isNull() ) {
605 addPropValue( a, VCDisplayStringProp,
"beep!" );
607 addPropValue( a, VCDisplayStringProp, alarm->text().toAscii().data() );
610 a = addProp( vtodo, VCAAlarmProp );
612 addPropValue( a, VCRunTimeProp, tmpStr.toUtf8() );
613 addPropValue( a, VCRepeatCountProp,
"1" );
614 addPropValue( a, VCAudioContentProp, QFile::encodeName( alarm->audioFile() ) );
616 a = addProp( vtodo, VCPAlarmProp );
618 addPropValue( a, VCRunTimeProp, tmpStr.toUtf8() );
619 addPropValue( a, VCRepeatCountProp,
"1" );
620 addPropValue( a, VCProcedureNameProp, QFile::encodeName( alarm->programFile() ) );
625 QString pilotId = anEvent->nonKDECustomProperty( KPilotIdProp );
626 if ( !pilotId.isEmpty() ) {
628 addPropValue( vtodo, KPilotIdProp, pilotId.toUtf8() );
629 addPropValue( vtodo, KPilotStatusProp,
630 anEvent->nonKDECustomProperty( KPilotStatusProp ).toUtf8() );
632 #if defined(KCALCORE_FOR_SYMBIAN)
633 if ( anEvent->nonKDECustomProperty( EPOCAgendaEntryTypeProp ).isEmpty() ) {
636 addPropValue( vtodo, EPOCAgendaEntryTypeProp,
"TODO" );
639 writeCustomProperties( vtodo, anEvent );
650 vevent = newVObject( VCEventProp );
653 tmpStr =
kDateTimeToISO( anEvent->dtStart(), !anEvent->allDay() );
654 addPropValue( vevent, VCDTstartProp, tmpStr.toUtf8() );
656 #if !defined(KCALCORE_FOR_MEEGO)
659 if ( anEvent->dtStart() != anEvent->dtEnd() ) {
661 addPropValue( vevent, VCDTendProp, tmpStr.toUtf8() );
666 addPropValue( vevent, VCDTendProp, tmpStr.toUtf8() );
671 addPropValue( vevent, VCDCreatedProp, tmpStr.toUtf8() );
674 addPropValue( vevent, VCUniqueStringProp,
675 anEvent->uid().toUtf8() );
678 tmpStr.sprintf(
"%i", anEvent->revision() );
679 addPropValue( vevent, VCSequenceProp, tmpStr.toUtf8() );
683 addPropValue( vevent, VCLastModifiedProp, tmpStr.toUtf8() );
687 if ( !anEvent->organizer()->email().isEmpty() ) {
688 tmpStr =
"MAILTO:" + anEvent->organizer()->email();
689 addPropValue( vevent, ICOrganizerProp, tmpStr.toUtf8() );
693 if ( anEvent->attendeeCount() > 0 ) {
694 Attendee::List::ConstIterator it;
695 for ( it = anEvent->attendees().constBegin(); it != anEvent->attendees().constEnd();
698 if ( !curAttendee->email().isEmpty() && !curAttendee->name().isEmpty() ) {
699 tmpStr =
"MAILTO:" + curAttendee->name() +
" <" + curAttendee->email() +
'>';
700 }
else if ( curAttendee->name().isEmpty() && curAttendee->email().isEmpty() ) {
702 kDebug() <<
"warning! this Event has an attendee w/o name or email!";
703 }
else if ( curAttendee->name().isEmpty() ) {
704 tmpStr =
"MAILTO: " + curAttendee->email();
706 tmpStr =
"MAILTO: " + curAttendee->name();
708 VObject *aProp = addPropValue( vevent, VCAttendeeProp, tmpStr.toUtf8() );
709 addPropValue( aProp, VCRSVPProp, curAttendee->RSVP() ?
"TRUE" :
"FALSE" );
710 addPropValue( aProp, VCStatusProp,
writeStatus( curAttendee->status() ) );
715 const Recurrence *recur = anEvent->recurrence();
717 bool validRecur =
true;
720 case Recurrence::rDaily:
721 tmpStr.sprintf(
"D%i ", recur->
frequency() );
723 case Recurrence::rWeekly:
724 tmpStr.sprintf(
"W%i ", recur->
frequency() );
725 for (
int i = 0; i < 7; ++i ) {
726 QBitArray days ( recur->
days() );
727 if ( days.testBit(i) ) {
732 case Recurrence::rMonthlyPos:
734 tmpStr.sprintf(
"MP%i ", recur->
frequency() );
736 QList<RecurrenceRule::WDayPos> tmpPositions = recur->
monthPositions();
737 for ( QList<RecurrenceRule::WDayPos>::ConstIterator posit = tmpPositions.constBegin();
738 posit != tmpPositions.constEnd(); ++posit ) {
739 int pos = (*posit).pos();
740 tmpStr2.sprintf(
"%i", ( pos > 0 ) ? pos : (-pos) );
751 case Recurrence::rMonthlyDay:
753 tmpStr.sprintf(
"MD%i ", recur->
frequency() );
755 const QList<int> tmpDays = recur->
monthDays();
756 for ( QList<int>::ConstIterator tmpDay = tmpDays.constBegin();
757 tmpDay != tmpDays.constEnd(); ++tmpDay ) {
758 tmpStr2.sprintf(
"%i ", *tmpDay );
763 case Recurrence::rYearlyMonth:
765 tmpStr.sprintf(
"YM%i ", recur->
frequency() );
768 const QList<int> months = recur->
yearMonths();
769 for ( QList<int>::ConstIterator mit = months.constBegin();
770 mit != months.constEnd(); ++mit ) {
771 tmpStr2.sprintf(
"%i ", *mit );
776 case Recurrence::rYearlyDay:
778 tmpStr.sprintf(
"YD%i ", recur->
frequency() );
780 const QList<int> tmpDays = recur->
yearDays();
781 for ( QList<int>::ConstIterator tmpDay = tmpDays.begin();
782 tmpDay != tmpDays.end(); ++tmpDay ) {
783 tmpStr2.sprintf(
"%i ", *tmpDay );
790 kDebug() <<
"ERROR, it should never get here in eventToVEvent!";
796 tmpStr2.sprintf(
"#%i", recur->
duration() );
798 }
else if ( recur->
duration() == -1 ) {
801 #if !defined(KCALCORE_FOR_MEEGO)
811 addPropValue( vevent, VCRRuleProp, tmpStr.toUtf8() );
817 DateList dateList = recur->exDates();
818 DateList::ConstIterator it;
821 for ( it = dateList.constBegin(); it != dateList.constEnd(); ++it ) {
825 if ( !tmpStr2.isEmpty() ) {
826 tmpStr2.truncate( tmpStr2.length() - 1 );
827 addPropValue( vevent, VCExpDateProp, tmpStr2.toUtf8() );
831 DateTimeList::ConstIterator idt;
834 for ( idt = dateTimeList.constBegin(); idt != dateTimeList.constEnd(); ++idt ) {
838 if ( !tmpStr2.isEmpty() ) {
839 tmpStr2.truncate( tmpStr2.length() - 1 );
840 addPropValue( vevent, VCExpDateProp, tmpStr2.toUtf8() );
844 if ( !anEvent->description().isEmpty() ) {
845 QByteArray in = anEvent->description().toUtf8();
847 KCodecs::quotedPrintableEncode( in, out,
true );
849 VObject *d = addPropValue( vevent, VCDescriptionProp, out );
850 addPropValue( d, VCEncodingProp, VCQuotedPrintableProp );
851 addPropValue( d, VCCharSetProp, VCUtf8Prop );
853 addPropValue( vevent, VCDescriptionProp, in );
858 if ( !anEvent->summary().isEmpty() ) {
859 QByteArray in = anEvent->summary().toUtf8();
861 KCodecs::quotedPrintableEncode( in, out,
true );
863 VObject *d = addPropValue( vevent, VCSummaryProp, out );
864 addPropValue( d, VCEncodingProp, VCQuotedPrintableProp );
865 addPropValue( d, VCCharSetProp, VCUtf8Prop );
867 addPropValue( vevent, VCSummaryProp, in );
872 if ( !anEvent->location().isEmpty() ) {
873 QByteArray in = anEvent->location().toUtf8();
875 KCodecs::quotedPrintableEncode( in, out,
true );
877 VObject *d = addPropValue( vevent, VCLocationProp, out );
878 addPropValue( d, VCEncodingProp, VCQuotedPrintableProp );
879 addPropValue( d, VCCharSetProp, VCUtf8Prop );
881 addPropValue( vevent, VCLocationProp, in );
890 const char *text = 0;
891 switch ( anEvent->secrecy() ) {
899 text =
"CONFIDENTIAL";
903 addPropValue( vevent, VCClassProp, text );
907 QStringList tmpStrList = anEvent->categories();
910 for ( QStringList::const_iterator it = tmpStrList.constBegin(); it != tmpStrList.constEnd();
913 if ( catStr[0] ==
' ' ) {
914 tmpStr += catStr.mid( 1 );
923 if ( !tmpStr.isEmpty() ) {
924 tmpStr.truncate( tmpStr.length() - 1 );
925 addPropValue( vevent, VCCategoriesProp, tmpStr.toUtf8() );
931 Attachment::List::ConstIterator atIt;
932 for ( atIt = attachments.constBegin(); atIt != attachments.constEnd(); ++atIt ) {
933 addPropValue( vevent, VCAttachProp, (*atIt)->uri().toUtf8() );
937 tmpStrList = anEvent->resources();
938 tmpStr = tmpStrList.join(
";" );
939 if ( !tmpStr.isEmpty() ) {
940 addPropValue( vevent, VCResourcesProp, tmpStr.toUtf8() );
944 Alarm::List::ConstIterator it2;
945 for ( it2 = anEvent->alarms().constBegin(); it2 != anEvent->alarms().constEnd(); ++it2 ) {
947 if ( alarm->enabled() ) {
950 a = addProp( vevent, VCDAlarmProp );
952 addPropValue( a, VCRunTimeProp, tmpStr.toUtf8() );
953 addPropValue( a, VCRepeatCountProp,
"1" );
954 if ( alarm->text().isNull() ) {
955 addPropValue( a, VCDisplayStringProp,
"beep!" );
957 addPropValue( a, VCDisplayStringProp, alarm->text().toAscii().data() );
960 a = addProp( vevent, VCAAlarmProp );
962 addPropValue( a, VCRunTimeProp, tmpStr.toUtf8() );
963 addPropValue( a, VCRepeatCountProp,
"1" );
964 addPropValue( a, VCAudioContentProp, QFile::encodeName( alarm->audioFile() ) );
967 a = addProp( vevent, VCPAlarmProp );
969 addPropValue( a, VCRunTimeProp, tmpStr.toUtf8() );
970 addPropValue( a, VCRepeatCountProp,
"1" );
971 addPropValue( a, VCProcedureNameProp, QFile::encodeName( alarm->programFile() ) );
977 tmpStr.sprintf(
"%i", anEvent->priority() );
978 addPropValue( vevent, VCPriorityProp, tmpStr.toUtf8() );
981 tmpStr.sprintf(
"%i", anEvent->transparency() );
982 addPropValue( vevent, VCTranspProp, tmpStr.toUtf8() );
985 if ( !anEvent->relatedTo().isEmpty() ) {
986 addPropValue( vevent, VCRelatedToProp, anEvent->relatedTo().toUtf8() );
989 QString pilotId = anEvent->nonKDECustomProperty( KPilotIdProp );
990 if ( !pilotId.isEmpty() ) {
992 addPropValue( vevent, KPilotIdProp, pilotId.toUtf8() );
993 addPropValue( vevent, KPilotStatusProp,
994 anEvent->nonKDECustomProperty( KPilotStatusProp ).toUtf8() );
997 #if defined(KCALCORE_FOR_SYMBIAN)
998 if ( anEvent->nonKDECustomProperty( EPOCAgendaEntryTypeProp ).isEmpty() ) {
1001 if ( anEvent->allDay() ) {
1002 addPropValue( vevent, EPOCAgendaEntryTypeProp,
"EVENT" );
1004 addPropValue( vevent, EPOCAgendaEntryTypeProp,
"APPOINTMENT" );
1008 if ( anEvent->hasRecurrenceId() ) {
1010 addPropValue( vevent, VCRecurrenceIdProp, tmpStr.toUtf8() );
1012 writeCustomProperties( vevent, anEvent );
1021 VObjectIterator voi;
1027 if ( ( vo = isAPropertyOf( vtodo, VCDCreatedProp ) ) != 0 ) {
1028 anEvent->setCreated(
ISOToKDateTime( s = fakeCString( vObjectUStringZValue( vo ) ) ) );
1033 vo = isAPropertyOf( vtodo, VCUniqueStringProp );
1037 anEvent->setUid( s = fakeCString( vObjectUStringZValue( vo ) ) );
1042 if ( ( vo = isAPropertyOf( vtodo, VCLastModifiedProp ) ) != 0 ) {
1043 anEvent->setLastModified(
ISOToKDateTime( s = fakeCString( vObjectUStringZValue( vo ) ) ) );
1046 anEvent->setLastModified( KDateTime::currentUtcDateTime() );
1051 if ( ( vo = isAPropertyOf( vtodo, ICOrganizerProp ) ) != 0 ) {
1052 anEvent->setOrganizer( s = fakeCString( vObjectUStringZValue( vo ) ) );
1055 if ( d->mCalendar->owner()->name() !=
"Unknown Name" ) {
1056 anEvent->setOrganizer( d->mCalendar->owner() );
1061 initPropIterator( &voi, vtodo );
1062 while ( moreIteration( &voi ) ) {
1063 vo = nextVObject( &voi );
1064 if ( strcmp( vObjectName( vo ), VCAttendeeProp ) == 0 ) {
1067 s = fakeCString( vObjectUStringZValue( vo ) );
1068 QString tmpStr = QString::fromUtf8( s );
1070 tmpStr = tmpStr.simplified();
1071 int emailPos1, emailPos2;
1072 if ( ( emailPos1 = tmpStr.indexOf(
'<' ) ) > 0 ) {
1074 emailPos2 = tmpStr.lastIndexOf(
'>' );
1076 tmpStr.mid( emailPos1 + 1,
1077 emailPos2 - ( emailPos1 + 1 ) ) ) );
1078 }
else if ( tmpStr.indexOf(
'@' ) > 0 ) {
1084 QString email = tmpStr.replace(
' ',
'.' );
1089 if ( ( vp = isAPropertyOf( vo, VCRSVPProp ) ) != 0 ) {
1090 a->setRSVP( vObjectStringZValue( vp ) );
1093 if ( ( vp = isAPropertyOf( vo, VCStatusProp ) ) != 0 ) {
1094 a->setStatus(
readStatus( vObjectStringZValue( vp ) ) );
1097 anEvent->addAttendee( a );
1102 if ( ( vo = isAPropertyOf( vtodo, VCDescriptionProp ) ) != 0 ) {
1103 s = fakeCString( vObjectUStringZValue( vo ) );
1104 anEvent->setDescription( QString::fromUtf8( s ), Qt::mightBeRichText( s ) );
1109 if ( ( vo = isAPropertyOf( vtodo, VCSummaryProp ) ) ) {
1110 s = fakeCString( vObjectUStringZValue( vo ) );
1111 anEvent->setSummary( QString::fromUtf8( s ), Qt::mightBeRichText( s ) );
1116 if ( ( vo = isAPropertyOf( vtodo, VCLocationProp ) ) != 0 ) {
1117 s = fakeCString( vObjectUStringZValue( vo ) );
1118 anEvent->setLocation( QString::fromUtf8( s ), Qt::mightBeRichText( s ) );
1124 if ( ( vo = isAPropertyOf( vtodo, VCStatusProp ) ) != 0 ) {
1125 s = fakeCString( vObjectUStringZValue( vo ) );
1126 if ( s && strcmp( s,
"COMPLETED" ) == 0 ) {
1127 anEvent->setCompleted(
true );
1129 anEvent->setCompleted(
false );
1133 anEvent->setCompleted(
false );
1137 if ( ( vo = isAPropertyOf( vtodo, VCCompletedProp ) ) != 0 ) {
1138 anEvent->setCompleted(
ISOToKDateTime( s = fakeCString( vObjectUStringZValue( vo ) ) ) );
1143 if ( ( vo = isAPropertyOf( vtodo, VCPriorityProp ) ) ) {
1144 s = fakeCString( vObjectUStringZValue( vo ) );
1146 anEvent->setPriority( atoi( s ) );
1151 anEvent->setAllDay(
false );
1154 if ( ( vo = isAPropertyOf( vtodo, VCDueProp ) ) != 0 ) {
1155 anEvent->setDtDue(
ISOToKDateTime( s = fakeCString( vObjectUStringZValue( vo ) ) ) );
1157 anEvent->setHasDueDate(
true );
1158 if ( anEvent->dtDue().time().hour() == 0 &&
1159 anEvent->dtDue().time().minute() == 0 &&
1160 anEvent->dtDue().time().second() == 0 ) {
1161 #if defined(KCALCORE_FOR_MEEGO)
1162 QDate dueDate = anEvent->dtDue().date();
1163 anEvent->setDtDue( KDateTime( dueDate, KDateTime::ClockTime ) );
1165 anEvent->setAllDay(
true );
1168 anEvent->setHasDueDate(
false );
1172 if ( ( vo = isAPropertyOf( vtodo, VCDTstartProp ) ) != 0 ) {
1173 anEvent->setDtStart(
ISOToKDateTime( s = fakeCString( vObjectUStringZValue( vo ) ) ) );
1175 anEvent->setHasStartDate(
true );
1176 if ( anEvent->dtStart().time().hour() == 0 &&
1177 anEvent->dtStart().time().minute() == 0 &&
1178 anEvent->dtStart().time().second() == 0 ) {
1179 #if defined(KCALCORE_FOR_MEEGO)
1180 QDate startDate = anEvent->dtStart().date();
1181 anEvent->setDtStart( KDateTime( startDate, KDateTime::ClockTime ) );
1183 anEvent->setAllDay(
true );
1186 anEvent->setHasStartDate(
false );
1190 if ( ( vo = isAPropertyOf( vtodo, VCRRuleProp ) ) != 0 ) {
1191 QString tmpStr = ( s = fakeCString( vObjectUStringZValue( vo ) ) );
1193 tmpStr.simplified();
1194 tmpStr = tmpStr.toUpper();
1197 uint type = Recurrence::rNone;
1198 if ( tmpStr.left(1) ==
"D" ) {
1199 type = Recurrence::rDaily;
1200 }
else if ( tmpStr.left(1) ==
"W" ) {
1201 type = Recurrence::rWeekly;
1204 if ( tmpStr.left(2) ==
"MP" ) {
1205 type = Recurrence::rMonthlyPos;
1206 }
else if ( tmpStr.left(2) ==
"MD" ) {
1207 type = Recurrence::rMonthlyDay;
1208 }
else if ( tmpStr.left(2) ==
"YM" ) {
1209 type = Recurrence::rYearlyMonth;
1210 }
else if ( tmpStr.left(2) ==
"YD" ) {
1211 type = Recurrence::rYearlyDay;
1215 if ( type != Recurrence::rNone ) {
1218 int index = tmpStr.indexOf(
' ' );
1219 int last = tmpStr.lastIndexOf(
' ' ) + 1;
1220 int rFreq = tmpStr.mid( typelen, ( index - 1 ) ).toInt();
1225 case Recurrence::rDaily:
1226 anEvent->recurrence()->setDaily(rFreq);
1229 case Recurrence::rWeekly:
1233 if ( index == last ) {
1235 qba.setBit( anEvent->dtStart().date().dayOfWeek() - 1 );
1238 while ( index < last ) {
1239 dayStr = tmpStr.mid( index, 3 );
1241 if ( dayNum >= 0 ) {
1242 qba.setBit( dayNum );
1247 anEvent->recurrence()->setWeekly( rFreq, qba );
1251 case Recurrence::rMonthlyPos:
1253 anEvent->recurrence()->setMonthly( rFreq );
1257 if ( index == last ) {
1259 tmpPos = anEvent->dtStart().date().day() / 7 + 1;
1260 if ( tmpPos == 5 ) {
1263 qba.setBit( anEvent->dtStart().date().dayOfWeek() - 1 );
1264 anEvent->recurrence()->addMonthlyPos( tmpPos, qba );
1267 while ( index < last ) {
1268 tmpPos = tmpStr.mid( index, 1 ).toShort();
1270 if ( tmpStr.mid( index, 1 ) ==
"-" ) {
1272 tmpPos = 0 - tmpPos;
1275 while (
numFromDay( tmpStr.mid( index, 3 ) ) >= 0 ) {
1276 int dayNum =
numFromDay( tmpStr.mid( index, 3 ) );
1277 qba.setBit( dayNum );
1280 anEvent->recurrence()->addMonthlyPos( tmpPos, qba );
1288 case Recurrence::rMonthlyDay:
1289 anEvent->recurrence()->setMonthly( rFreq );
1290 if( index == last ) {
1292 short tmpDay = anEvent->dtStart().date().day();
1293 anEvent->recurrence()->addMonthlyDate( tmpDay );
1296 while ( index < last ) {
1297 int index2 = tmpStr.indexOf(
' ', index );
1298 if ( ( tmpStr.mid( ( index2 - 1 ), 1 ) ==
"-" ) ||
1299 ( tmpStr.mid( ( index2 - 1 ), 1 ) ==
"+" ) ) {
1300 index2 = index2 - 1;
1302 short tmpDay = tmpStr.mid( index, ( index2 - index ) ).toShort();
1304 if ( tmpStr.mid( index, 1 ) ==
"-" ) {
1305 tmpDay = 0 - tmpDay;
1308 anEvent->recurrence()->addMonthlyDate( tmpDay );
1313 case Recurrence::rYearlyMonth:
1314 anEvent->recurrence()->setYearly( rFreq );
1316 if ( index == last ) {
1318 short tmpMonth = anEvent->dtStart().date().month();
1319 anEvent->recurrence()->addYearlyMonth( tmpMonth );
1322 while ( index < last ) {
1323 int index2 = tmpStr.indexOf(
' ', index );
1324 short tmpMonth = tmpStr.mid( index, ( index2 - index ) ).toShort();
1326 anEvent->recurrence()->addYearlyMonth( tmpMonth );
1331 case Recurrence::rYearlyDay:
1332 anEvent->recurrence()->setYearly( rFreq );
1334 if ( index == last ) {
1336 short tmpDay = anEvent->dtStart().date().dayOfYear();
1337 anEvent->recurrence()->addYearlyDay( tmpDay );
1340 while ( index < last ) {
1341 int index2 = tmpStr.indexOf(
' ', index );
1342 short tmpDay = tmpStr.mid( index, ( index2 - index ) ).toShort();
1344 anEvent->recurrence()->addYearlyDay( tmpDay );
1355 if ( tmpStr.mid( index, 1 ) ==
"#" ) {
1358 int rDuration = tmpStr.mid( index, tmpStr.length() - index ).toInt();
1359 if ( rDuration > 0 ) {
1360 anEvent->recurrence()->setDuration( rDuration );
1362 }
else if ( tmpStr.indexOf(
'T', index ) != -1 ) {
1363 KDateTime rEndDate =
ISOToKDateTime( tmpStr.mid( index, tmpStr.length() - index ) );
1364 anEvent->recurrence()->setEndDateTime( rEndDate );
1367 kDebug() <<
"we don't understand this type of recurrence!";
1372 if ( ( vo = isAPropertyOf( vtodo, VCExpDateProp ) ) != 0 ) {
1373 s = fakeCString( vObjectUStringZValue( vo ) );
1374 QStringList exDates = QString::fromUtf8( s ).split(
',' );
1375 QStringList::ConstIterator it;
1376 for ( it = exDates.constBegin(); it != exDates.constEnd(); ++it ) {
1378 if ( exDate.time().hour() == 0 &&
1379 exDate.time().minute() == 0 &&
1380 exDate.time().second() == 0 ) {
1381 anEvent->recurrence()->addExDate(
ISOToQDate( *it ) );
1383 anEvent->recurrence()->addExDateTime( exDate );
1390 if ( ( vo = isAPropertyOf( vtodo, VCDAlarmProp ) ) ) {
1394 a = isAPropertyOf( vo, VCRunTimeProp );
1395 b = isAPropertyOf( vo, VCDisplayStringProp );
1398 alarm = anEvent->newAlarm();
1400 alarm->setTime(
ISOToKDateTime( s = fakeCString( vObjectUStringZValue( a ) ) ) );
1403 alarm->setEnabled(
true );
1405 s = fakeCString( vObjectUStringZValue( b ) );
1406 alarm->setDisplayAlarm( QString( s ) );
1409 alarm->setDisplayAlarm( QString() );
1414 if ( ( vo = isAPropertyOf( vtodo, VCAAlarmProp ) ) ) {
1418 a = isAPropertyOf( vo, VCRunTimeProp );
1419 b = isAPropertyOf( vo, VCAudioContentProp );
1422 alarm = anEvent->newAlarm();
1424 alarm->setTime(
ISOToKDateTime( s = fakeCString( vObjectUStringZValue( a ) ) ) );
1427 alarm->setEnabled(
true );
1429 s = fakeCString( vObjectUStringZValue( b ) );
1430 alarm->setAudioAlarm( QFile::decodeName( s ) );
1433 alarm->setAudioAlarm( QString() );
1438 if ( ( vo = isAPropertyOf( vtodo, VCPAlarmProp ) ) ) {
1442 a = isAPropertyOf( vo, VCRunTimeProp );
1443 b = isAPropertyOf( vo, VCProcedureNameProp );
1446 alarm = anEvent->newAlarm();
1448 alarm->setTime(
ISOToKDateTime( s = fakeCString( vObjectUStringZValue( a ) ) ) );
1451 alarm->setEnabled(
true );
1454 s = fakeCString( vObjectUStringZValue( b ) );
1455 alarm->setProcedureAlarm( QFile::decodeName( s ) );
1458 alarm->setProcedureAlarm( QString() );
1464 if ( ( vo = isAPropertyOf( vtodo, VCRelatedToProp ) ) != 0 ) {
1465 anEvent->setRelatedTo( s = fakeCString( vObjectUStringZValue( vo ) ) );
1467 d->mTodosRelate.append( anEvent );
1472 if ( ( vo = isAPropertyOf( vtodo, VCClassProp ) ) != 0 ) {
1473 s = fakeCString( vObjectUStringZValue( vo ) );
1474 if ( s && strcmp( s,
"PRIVATE" ) == 0 ) {
1476 }
else if ( s && strcmp( s,
"CONFIDENTIAL" ) == 0 ) {
1481 anEvent->setSecrecy( secrecy );
1484 if ( ( vo = isAPropertyOf( vtodo, VCCategoriesProp ) ) != 0 ) {
1485 s = fakeCString( vObjectUStringZValue( vo ) );
1486 QString categories = QString::fromUtf8( s );
1488 QStringList tmpStrList = categories.split(
';' );
1489 anEvent->setCategories( tmpStrList );
1493 if ( ( vo = isAPropertyOf( vtodo, KPilotIdProp ) ) ) {
1494 anEvent->setNonKDECustomProperty(
1495 KPilotIdProp, QString::fromUtf8( s = fakeCString( vObjectUStringZValue( vo ) ) ) );
1497 if ( ( vo = isAPropertyOf( vtodo, KPilotStatusProp ) ) ) {
1498 anEvent->setNonKDECustomProperty(
1499 KPilotStatusProp, QString::fromUtf8( s = fakeCString( vObjectUStringZValue( vo ) ) ) );
1502 anEvent->setNonKDECustomProperty( KPilotStatusProp, QString::number(
int( SYNCMOD ) ) );
1512 VObjectIterator voi;
1518 if ( ( vo = isAPropertyOf( vevent, VCDCreatedProp ) ) != 0 ) {
1519 anEvent->setCreated(
ISOToKDateTime( s = fakeCString( vObjectUStringZValue( vo ) ) ) );
1524 vo = isAPropertyOf( vevent, VCUniqueStringProp );
1528 anEvent->setUid( s = fakeCString( vObjectUStringZValue( vo ) ) );
1532 #if defined(KCALCORE_FOR_SYMBIAN)
1534 vo = isAPropertyOf( vevent, VCRecurrenceIdProp );
1536 anEvent->setRecurrenceId(
ISOToKDateTime( s = fakeCString( vObjectUStringZValue( vo ) ) ) );
1543 anEvent->setRevision( 0 );
1544 if ( ( vo = isAPropertyOf( vevent, VCSequenceProp ) ) != 0 ) {
1545 s = fakeCString( vObjectUStringZValue( vo ) );
1547 anEvent->setRevision( atoi( s ) );
1553 if ( ( vo = isAPropertyOf( vevent, VCLastModifiedProp ) ) != 0 ) {
1554 anEvent->setLastModified(
ISOToKDateTime( s = fakeCString( vObjectUStringZValue( vo ) ) ) );
1557 anEvent->setLastModified( KDateTime::currentUtcDateTime() );
1562 if ( ( vo = isAPropertyOf( vevent, ICOrganizerProp ) ) != 0 ) {
1564 anEvent->setOrganizer( s = fakeCString( vObjectUStringZValue( vo ) ) );
1567 if ( d->mCalendar->owner()->name() !=
"Unknown Name" ) {
1568 anEvent->setOrganizer( d->mCalendar->owner() );
1573 initPropIterator( &voi, vevent );
1574 while ( moreIteration( &voi ) ) {
1575 vo = nextVObject( &voi );
1576 if ( strcmp( vObjectName( vo ), VCAttendeeProp ) == 0 ) {
1579 s = fakeCString( vObjectUStringZValue( vo ) );
1580 QString tmpStr = QString::fromUtf8( s );
1582 tmpStr = tmpStr.simplified();
1583 int emailPos1, emailPos2;
1584 if ( ( emailPos1 = tmpStr.indexOf(
'<' ) ) > 0 ) {
1586 emailPos2 = tmpStr.lastIndexOf(
'>' );
1588 tmpStr.mid( emailPos1 + 1,
1589 emailPos2 - ( emailPos1 + 1 ) ) ) );
1590 }
else if ( tmpStr.indexOf(
'@' ) > 0 ) {
1595 QString email = tmpStr.replace(
' ',
'.' );
1600 if ( ( vp = isAPropertyOf( vo, VCRSVPProp ) ) != 0 ) {
1601 a->setRSVP( vObjectStringZValue( vp ) );
1604 if ( ( vp = isAPropertyOf( vo, VCStatusProp ) ) != 0 ) {
1605 a->setStatus(
readStatus( vObjectStringZValue( vp ) ) );
1608 anEvent->addAttendee( a );
1621 anEvent->setAllDay(
false );
1624 if ( ( vo = isAPropertyOf( vevent, VCDTstartProp ) ) != 0 ) {
1625 anEvent->setDtStart(
ISOToKDateTime( s = fakeCString( vObjectUStringZValue( vo ) ) ) );
1628 if ( anEvent->dtStart().time().hour() == 0 &&
1629 anEvent->dtStart().time().minute() == 0 &&
1630 anEvent->dtStart().time().second() == 0 ) {
1631 #if defined(KCALCORE_FOR_MEEGO)
1632 QDate startDate = anEvent->dtStart().date();
1633 anEvent->setDtStart( KDateTime( startDate, KDateTime::ClockTime ) );
1635 anEvent->setAllDay(
true );
1640 if ( ( vo = isAPropertyOf( vevent, VCDTendProp ) ) != 0 ) {
1641 anEvent->setDtEnd(
ISOToKDateTime( s = fakeCString( vObjectUStringZValue( vo ) ) ) );
1644 if ( anEvent->dtEnd().time().hour() == 0 &&
1645 anEvent->dtEnd().time().minute() == 0 &&
1646 anEvent->dtEnd().time().second() == 0 ) {
1647 #if defined(KCALCORE_FOR_MEEGO)
1648 QDate endDate = anEvent->dtEnd().date();
1649 anEvent->setDtEnd( KDateTime( endDate, KDateTime::ClockTime ) );
1651 anEvent->setAllDay(
true );
1654 #if defined(KCALCORE_FOR_MEEGO)
1655 if ( anEvent->allDay() ) {
1656 if ( anEvent->dtEnd() == anEvent->dtStart() ) {
1657 anEvent->setDtEnd( anEvent->dtEnd().addDays( 1 ) );
1664 if ( !isAPropertyOf( vevent, VCDTstartProp ) ) {
1665 anEvent->setDtStart( anEvent->dtEnd() );
1667 if ( ! isAPropertyOf( vevent, VCDTendProp ) ) {
1668 anEvent->setDtEnd( anEvent->dtStart() );
1674 if ( ( vo = isAPropertyOf( vevent, VCRRuleProp ) ) != 0 ) {
1675 QString tmpStr = ( s = fakeCString( vObjectUStringZValue( vo ) ) );
1677 tmpStr.simplified();
1678 tmpStr = tmpStr.toUpper();
1681 uint type = Recurrence::rNone;
1682 if ( tmpStr.left(1) ==
"D" ) {
1683 type = Recurrence::rDaily;
1684 }
else if ( tmpStr.left(1) ==
"W" ) {
1685 type = Recurrence::rWeekly;
1688 if ( tmpStr.left(2) ==
"MP" ) {
1689 type = Recurrence::rMonthlyPos;
1690 }
else if ( tmpStr.left(2) ==
"MD" ) {
1691 type = Recurrence::rMonthlyDay;
1692 }
else if ( tmpStr.left(2) ==
"YM" ) {
1693 type = Recurrence::rYearlyMonth;
1694 }
else if ( tmpStr.left(2) ==
"YD" ) {
1695 type = Recurrence::rYearlyDay;
1699 if ( type != Recurrence::rNone ) {
1702 int index = tmpStr.indexOf(
' ' );
1703 int last = tmpStr.lastIndexOf(
' ' ) + 1;
1704 int rFreq = tmpStr.mid( typelen, ( index - 1 ) ).toInt();
1709 case Recurrence::rDaily:
1710 anEvent->recurrence()->setDaily(rFreq);
1713 case Recurrence::rWeekly:
1717 if ( index == last ) {
1719 qba.setBit( anEvent->dtStart().date().dayOfWeek() - 1 );
1722 while ( index < last ) {
1723 dayStr = tmpStr.mid( index, 3 );
1725 if ( dayNum >= 0 ) {
1726 qba.setBit( dayNum );
1731 anEvent->recurrence()->setWeekly( rFreq, qba );
1735 case Recurrence::rMonthlyPos:
1737 anEvent->recurrence()->setMonthly( rFreq );
1741 if ( index == last ) {
1743 tmpPos = anEvent->dtStart().date().day() / 7 + 1;
1744 if ( tmpPos == 5 ) {
1747 qba.setBit( anEvent->dtStart().date().dayOfWeek() - 1 );
1748 anEvent->recurrence()->addMonthlyPos( tmpPos, qba );
1751 while ( index < last ) {
1752 tmpPos = tmpStr.mid( index, 1 ).toShort();
1754 if ( tmpStr.mid( index, 1 ) ==
"-" ) {
1756 tmpPos = 0 - tmpPos;
1759 while (
numFromDay( tmpStr.mid( index, 3 ) ) >= 0 ) {
1760 int dayNum =
numFromDay( tmpStr.mid( index, 3 ) );
1761 qba.setBit( dayNum );
1764 anEvent->recurrence()->addMonthlyPos( tmpPos, qba );
1772 case Recurrence::rMonthlyDay:
1773 anEvent->recurrence()->setMonthly( rFreq );
1774 if( index == last ) {
1776 short tmpDay = anEvent->dtStart().date().day();
1777 anEvent->recurrence()->addMonthlyDate( tmpDay );
1780 while ( index < last ) {
1781 int index2 = tmpStr.indexOf(
' ', index );
1782 if ( ( tmpStr.mid( ( index2 - 1 ), 1 ) ==
"-" ) ||
1783 ( tmpStr.mid( ( index2 - 1 ), 1 ) ==
"+" ) ) {
1784 index2 = index2 - 1;
1786 short tmpDay = tmpStr.mid( index, ( index2 - index ) ).toShort();
1788 if ( tmpStr.mid( index, 1 ) ==
"-" ) {
1789 tmpDay = 0 - tmpDay;
1792 anEvent->recurrence()->addMonthlyDate( tmpDay );
1797 case Recurrence::rYearlyMonth:
1798 anEvent->recurrence()->setYearly( rFreq );
1800 if ( index == last ) {
1802 short tmpMonth = anEvent->dtStart().date().month();
1803 anEvent->recurrence()->addYearlyMonth( tmpMonth );
1806 while ( index < last ) {
1807 int index2 = tmpStr.indexOf(
' ', index );
1808 short tmpMonth = tmpStr.mid( index, ( index2 - index ) ).toShort();
1810 anEvent->recurrence()->addYearlyMonth( tmpMonth );
1815 case Recurrence::rYearlyDay:
1816 anEvent->recurrence()->setYearly( rFreq );
1818 if ( index == last ) {
1820 short tmpDay = anEvent->dtStart().date().dayOfYear();
1821 anEvent->recurrence()->addYearlyDay( tmpDay );
1824 while ( index < last ) {
1825 int index2 = tmpStr.indexOf(
' ', index );
1826 short tmpDay = tmpStr.mid( index, ( index2 - index ) ).toShort();
1828 anEvent->recurrence()->addYearlyDay( tmpDay );
1839 if ( tmpStr.mid( index, 1 ) ==
"#" ) {
1842 int rDuration = tmpStr.mid( index, tmpStr.length() - index ).toInt();
1843 if ( rDuration > 0 ) {
1844 anEvent->recurrence()->setDuration( rDuration );
1846 }
else if ( tmpStr.indexOf(
'T', index ) != -1 ) {
1847 KDateTime rEndDate =
ISOToKDateTime( tmpStr.mid( index, tmpStr.length() - index ) );
1848 anEvent->recurrence()->setEndDateTime( rEndDate );
1853 kDebug() <<
"we don't understand this type of recurrence!";
1858 if ( ( vo = isAPropertyOf( vevent, VCExpDateProp ) ) != 0 ) {
1859 s = fakeCString( vObjectUStringZValue( vo ) );
1860 QStringList exDates = QString::fromUtf8( s ).split(
',' );
1861 QStringList::ConstIterator it;
1862 for ( it = exDates.constBegin(); it != exDates.constEnd(); ++it ) {
1864 if ( exDate.time().hour() == 0 &&
1865 exDate.time().minute() == 0 &&
1866 exDate.time().second() == 0 ) {
1867 anEvent->recurrence()->addExDate(
ISOToQDate( *it ) );
1869 anEvent->recurrence()->addExDateTime( exDate );
1876 if ( ( vo = isAPropertyOf( vevent, VCSummaryProp ) ) ) {
1877 s = fakeCString( vObjectUStringZValue( vo ) );
1878 anEvent->setSummary( QString::fromUtf8( s ), Qt::mightBeRichText( s ) );
1883 if ( ( vo = isAPropertyOf( vevent, VCDescriptionProp ) ) != 0 ) {
1884 s = fakeCString( vObjectUStringZValue( vo ) );
1885 bool isRich = Qt::mightBeRichText( s );
1886 if ( !anEvent->description().isEmpty() ) {
1887 anEvent->setDescription(
1888 anEvent->description() +
'\n' + QString::fromUtf8( s ), isRich );
1890 anEvent->setDescription( QString::fromUtf8( s ), isRich );
1896 if ( ( vo = isAPropertyOf( vevent, VCLocationProp ) ) != 0 ) {
1897 s = fakeCString( vObjectUStringZValue( vo ) );
1898 anEvent->setLocation( QString::fromUtf8( s ), Qt::mightBeRichText( s ) );
1904 if ( anEvent->summary().isEmpty() && !( anEvent->description().isEmpty() ) ) {
1905 QString tmpStr = anEvent->description().simplified();
1906 anEvent->setDescription(
"" );
1907 anEvent->setSummary( tmpStr );
1912 if ( ( vo = isAPropertyOf( vevent, VCStatusProp ) ) != 0 ) {
1913 QString tmpStr( s = fakeCString( vObjectUStringZValue( vo ) ) );
1924 if ( ( vo = isAPropertyOf( vevent, VCClassProp ) ) != 0 ) {
1925 s = fakeCString( vObjectUStringZValue( vo ) );
1926 if ( s && strcmp( s,
"PRIVATE" ) == 0 ) {
1928 }
else if ( s && strcmp( s,
"CONFIDENTIAL" ) == 0 ) {
1933 anEvent->setSecrecy( secrecy );
1936 if ( ( vo = isAPropertyOf( vevent, VCCategoriesProp ) ) != 0 ) {
1937 s = fakeCString( vObjectUStringZValue( vo ) );
1938 QString categories = QString::fromUtf8( s );
1940 QStringList tmpStrList = categories.split(
',' );
1941 anEvent->setCategories( tmpStrList );
1945 initPropIterator( &voi, vevent );
1946 while ( moreIteration( &voi ) ) {
1947 vo = nextVObject( &voi );
1948 if ( strcmp( vObjectName( vo ), VCAttachProp ) == 0 ) {
1949 s = fakeCString( vObjectUStringZValue( vo ) );
1956 if ( ( vo = isAPropertyOf( vevent, VCResourcesProp ) ) != 0 ) {
1957 QString resources = ( s = fakeCString( vObjectUStringZValue( vo ) ) );
1959 QStringList tmpStrList = resources.split(
';' );
1960 anEvent->setResources( tmpStrList );
1964 if ( ( vo = isAPropertyOf( vevent, VCDAlarmProp ) ) ) {
1968 a = isAPropertyOf( vo, VCRunTimeProp );
1969 b = isAPropertyOf( vo, VCDisplayStringProp );
1972 alarm = anEvent->newAlarm();
1974 alarm->setTime(
ISOToKDateTime( s = fakeCString( vObjectUStringZValue( a ) ) ) );
1977 alarm->setEnabled(
true );
1980 s = fakeCString( vObjectUStringZValue( b ) );
1981 alarm->setDisplayAlarm( QString( s ) );
1984 alarm->setDisplayAlarm( QString() );
1989 if ( ( vo = isAPropertyOf( vevent, VCAAlarmProp ) ) ) {
1993 a = isAPropertyOf( vo, VCRunTimeProp );
1994 b = isAPropertyOf( vo, VCAudioContentProp );
1997 alarm = anEvent->newAlarm();
1999 alarm->setTime(
ISOToKDateTime( s = fakeCString( vObjectUStringZValue( a ) ) ) );
2002 alarm->setEnabled(
true );
2005 s = fakeCString( vObjectUStringZValue( b ) );
2006 alarm->setAudioAlarm( QFile::decodeName( s ) );
2009 alarm->setAudioAlarm( QString() );
2014 if ( ( vo = isAPropertyOf( vevent, VCPAlarmProp ) ) ) {
2018 a = isAPropertyOf( vo, VCRunTimeProp );
2019 b = isAPropertyOf( vo, VCProcedureNameProp );
2022 alarm = anEvent->newAlarm();
2024 alarm->setTime(
ISOToKDateTime( s = fakeCString( vObjectUStringZValue( a ) ) ) );
2027 alarm->setEnabled(
true );
2030 s = fakeCString( vObjectUStringZValue( b ) );
2031 alarm->setProcedureAlarm( QFile::decodeName( s ) );
2034 alarm->setProcedureAlarm( QString() );
2040 if ( ( vo = isAPropertyOf( vevent, VCPriorityProp ) ) ) {
2041 s = fakeCString( vObjectUStringZValue( vo ) );
2043 anEvent->setPriority( atoi( s ) );
2049 if ( ( vo = isAPropertyOf( vevent, VCTranspProp ) ) != 0 ) {
2050 s = fakeCString( vObjectUStringZValue( vo ) );
2059 if ( ( vo = isAPropertyOf( vevent, VCRelatedToProp ) ) != 0 ) {
2060 anEvent->setRelatedTo( s = fakeCString( vObjectUStringZValue( vo ) ) );
2062 d->mEventsRelate.append( anEvent );
2066 if ( ( vo = isAPropertyOf( vevent, KPilotIdProp ) ) ) {
2067 anEvent->setNonKDECustomProperty(
2068 KPilotIdProp, QString::fromUtf8( s = fakeCString( vObjectUStringZValue( vo ) ) ) );
2070 if ( ( vo = isAPropertyOf( vevent, KPilotStatusProp ) ) ) {
2071 anEvent->setNonKDECustomProperty(
2072 KPilotStatusProp, QString::fromUtf8( s = fakeCString( vObjectUStringZValue( vo ) ) ) );
2075 anEvent->setNonKDECustomProperty( KPilotStatusProp, QString::number(
int( SYNCMOD ) ) );
2080 readCustomProperties( vevent, anEvent );
2087 qDebug() << timezone;
2088 QString pZone = timezone.mid( timezone.indexOf(
"TZID:VCAL" ) + 9 );
2089 return pZone.mid( 0, pZone.indexOf( QChar( QLatin1Char(
'\n' ) ) ) );
2094 if ( !timezone.contains(
"BEGIN:DAYLIGHT" ) ) {
2098 timezone = timezone.mid( timezone.indexOf(
"BEGIN:DAYLIGHT" ) );
2099 timezone = timezone.mid( timezone.indexOf(
"TZNAME:" ) + 7 );
2100 QString sStart = timezone.mid( 0, ( timezone.indexOf(
"COMMENT:" ) ) );
2102 timezone = timezone.mid( timezone.indexOf(
"TZOFFSETTO:" ) + 11 );
2103 QString sOffset = timezone.mid( 0, ( timezone.indexOf(
"DTSTART:" ) ) );
2105 sOffset.insert( 3, QString(
":" ) );
2106 timezone = timezone.mid( timezone.indexOf(
"TZNAME:" ) + 7 );
2107 QString sEnd = timezone.mid( 0, ( timezone.indexOf(
"COMMENT:" ) ) );
2110 return "TRUE;" + sOffset +
';' + sStart +
';' + sEnd +
";;";
2117 if ( !qd.isValid() ) {
2121 tmpStr.sprintf(
"%.2d%.2d%.2d", qd.year(), qd.month(), qd.day() );
2130 if ( !dt.isValid() ) {
2136 tmpDT = dt.toUtc().dateTime();
2138 #if !defined(KCALCORE_FOR_MEEGO)
2139 tmpDT = dt.toTimeSpec( d->mCalendar->timeSpec() ).dateTime();
2141 tmpDT = dt.dateTime();
2144 tmpStr.sprintf(
"%.2d%.2d%.2dT%.2d%.2d%.2d",
2145 tmpDT.date().year(), tmpDT.date().month(),
2146 tmpDT.date().day(), tmpDT.time().hour(),
2147 tmpDT.time().minute(), tmpDT.time().second() );
2148 if ( zulu || dt.isUtc() ) {
2159 int year, month, day, hour, minute, second;
2162 year = tmpStr.left( 4 ).toInt();
2163 month = tmpStr.mid( 4, 2 ).toInt();
2164 day = tmpStr.mid( 6, 2 ).toInt();
2165 hour = tmpStr.mid( 9, 2 ).toInt();
2166 minute = tmpStr.mid( 11, 2 ).toInt();
2167 second = tmpStr.mid( 13, 2 ).toInt();
2168 tmpDate.setYMD( year, month, day );
2169 tmpTime.setHMS( hour, minute, second );
2171 if ( tmpDate.isValid() && tmpTime.isValid() ) {
2173 if ( dtStr.at( dtStr.length() - 1 ) ==
'Z' ) {
2174 return KDateTime( tmpDate, tmpTime, KDateTime::UTC );
2176 return KDateTime( tmpDate, tmpTime, d->mCalendar->timeSpec() );
2185 int year, month, day;
2187 year = dateStr.left( 4 ).toInt();
2188 month = dateStr.mid( 4, 2 ).toInt();
2189 day = dateStr.mid( 6, 2 ).toInt();
2191 return QDate( year, month, day );
2204 QString str = s.trimmed();
2209 if ( str.size() <= ofs ) {
2212 if ( str[ofs] ==
'-' ) {
2215 }
else if ( str[ofs] ==
'+' ) {
2218 if ( str.size() <= ofs ) {
2225 if ( str.size() < ( ofs + 2 ) ) {
2229 v = str.mid( ofs, 2 ).toInt( &ok ) * 60;
2235 if ( str.size() > ofs ) {
2236 if ( str[ofs] ==
':' ) {
2239 if ( str.size() > ofs ) {
2240 if ( str.size() < ( ofs + 2 ) ) {
2243 v += str.mid( ofs, 2 ).toInt( &ok );
2249 result = v * mod * 60;
2258 Q_UNUSED( notebook );
2263 VObject *curVO, *curVOProp;
2265 bool hasTimeZone =
false;
2266 KDateTime::Spec previousSpec;
2268 if ( ( curVO = isAPropertyOf( vcal, ICMethodProp ) ) != 0 ) {
2269 char *methodType = 0;
2270 methodType = fakeCString( vObjectUStringZValue( curVO ) );
2271 kDebug() <<
"This calendar is an iTIP transaction of type '"
2272 << methodType <<
"'";
2273 deleteStr( methodType );
2277 if ( ( curVO = isAPropertyOf( vcal, VCProdIdProp ) ) != 0 ) {
2278 char *s = fakeCString( vObjectUStringZValue( curVO ) );
2279 if ( !s || strcmp(
productId().toUtf8(), s ) != 0 ) {
2280 kDebug() <<
"This vCalendar file was not created by KOrganizer or"
2281 <<
"any other product we support. Loading anyway...";
2288 if ( ( curVO = isAPropertyOf( vcal, VCVersionProp ) ) != 0 ) {
2289 char *s = fakeCString( vObjectUStringZValue( curVO ) );
2290 if ( !s || strcmp( _VCAL_VERSION, s ) != 0 ) {
2291 kDebug() <<
"This vCalendar file has version" << s
2292 <<
"We only support" << _VCAL_VERSION;
2298 if ( ( curVO = isAPropertyOf( vcal, VCTimeZoneProp ) ) != 0 ) {
2299 char *s = fakeCString( vObjectUStringZValue( curVO ) );
2301 QString name =
"VCAL" + ts;
2314 kDebug() <<
"got standard offset" << ts << utcOffset;
2317 KDateTime dt = KDateTime( QDateTime( QDate( 1900, 1, 1 ), QTime( 0, 0, 0 ) ) );
2318 tz = QString(
"STD;%1;false;%2" ).arg( QString::number( utcOffset ) ).arg( dt.toString() );
2319 tzList.append( tz );
2322 initPropIterator( &i, vcal );
2323 while ( moreIteration( &i ) ) {
2324 curVO = nextVObject( &i );
2325 if ( strcmp( vObjectName( curVO ), VCDayLightProp ) == 0 ) {
2326 char *s = fakeCString( vObjectUStringZValue( curVO ) );
2327 QString dst = QString( s );
2328 QStringList argl = dst.split(
',' );
2332 if ( argl.size() < 4 ) {
2337 if ( argl[0] !=
"TRUE" ) {
2343 kDebug() <<
"got DST offset" << argl[1] << utcOffsetDst;
2345 QString strEndDate = argl[3];
2348 QString strStartDate = argl[2];
2351 QString strRealEndDate = strEndDate;
2352 QString strRealStartDate = strStartDate;
2353 KDateTime realEndDate = endDate;
2354 KDateTime realStartDate = startDate;
2356 if ( endDate < startDate ) {
2357 strRealEndDate = strStartDate;
2358 strRealStartDate = strEndDate;
2359 realEndDate = startDate;
2360 realStartDate = endDate;
2362 tz = QString(
"%1;%2;false;%3" ).
2363 arg( strRealEndDate ).
2364 arg( QString::number( utcOffset ) ).
2365 arg( realEndDate.toString() );
2366 tzList.append( tz );
2368 tz = QString(
"%1;%2;true;%3" ).
2369 arg( strRealStartDate ).
2370 arg( QString::number( utcOffsetDst ) ).
2371 arg( realStartDate.toString() );
2372 tzList.append( tz );
2374 kDebug() <<
"unable to parse dst" << argl[1];
2381 if ( !zone.isValid() ) {
2382 kDebug() <<
"zone is not valid, parsing error" << tzList;
2384 previousSpec = d->mCalendar->timeSpec();
2385 d->mCalendar->setTimeZoneId( name );
2389 kDebug() <<
"unable to parse tzoffset" << ts;
2394 d->mEventsRelate.clear();
2395 d->mTodosRelate.clear();
2397 initPropIterator( &i, vcal );
2400 while ( moreIteration( &i ) ) {
2401 curVO = nextVObject( &i );
2406 if ( strcmp( vObjectName( curVO ), VCEventProp ) == 0 ) {
2408 if ( ( curVOProp = isAPropertyOf( curVO, KPilotStatusProp ) ) != 0 ) {
2410 s = fakeCString( vObjectUStringZValue( curVOProp ) );
2413 if ( atoi( s ) == SYNCDEL ) {
2415 kDebug() <<
"skipping pilot-deleted event";
2422 if ( !isAPropertyOf( curVO, VCDTstartProp ) &&
2423 !isAPropertyOf( curVO, VCDTendProp ) ) {
2424 kDebug() <<
"found a VEvent with no DTSTART and no DTEND! Skipping...";
2430 if ( hasTimeZone && !anEvent->allDay() && anEvent->dtStart().isUtc() ) {
2435 int utcOffSet = anEvent->dtStart().utcOffset();
2436 KDateTime dtStart( anEvent->dtStart().dateTime().addSecs( utcOffSet ),
2437 d->mCalendar->timeSpec() );
2438 KDateTime dtEnd( anEvent->dtEnd().dateTime().addSecs( utcOffSet ),
2439 d->mCalendar->timeSpec() );
2440 anEvent->setDtStart( dtStart );
2441 anEvent->setDtEnd( dtEnd );
2443 Event::Ptr old = !anEvent->hasRecurrenceId() ?
2444 d->mCalendar->event( anEvent->uid() ) :
2445 d->mCalendar->event( anEvent->uid(), anEvent->recurrenceId() );
2449 d->mCalendar->deleteEvent( old );
2450 removeAllVCal( d->mEventsRelate, old );
2451 }
else if ( anEvent->revision() > old->revision() ) {
2452 d->mCalendar->deleteEvent( old );
2453 removeAllVCal( d->mEventsRelate, old );
2454 d->mCalendar->addEvent( anEvent );
2456 }
else if ( deleted ) {
2457 old = !anEvent->hasRecurrenceId() ?
2458 d->mCalendar->deletedEvent( anEvent->uid() ) :
2459 d->mCalendar->deletedEvent( anEvent->uid(), anEvent->recurrenceId() );
2461 d->mCalendar->addEvent( anEvent );
2462 d->mCalendar->deleteEvent( anEvent );
2465 d->mCalendar->addEvent( anEvent );
2468 }
else if ( strcmp( vObjectName( curVO ), VCTodoProp ) == 0 ) {
2471 if ( hasTimeZone && !aTodo->allDay() && aTodo->dtStart().isUtc() ) {
2476 int utcOffSet = aTodo->dtStart().utcOffset();
2477 KDateTime dtStart( aTodo->dtStart().dateTime().addSecs( utcOffSet ),
2478 d->mCalendar->timeSpec() );
2479 aTodo->setDtStart( dtStart );
2480 if ( aTodo->hasDueDate() ) {
2481 KDateTime dtDue( aTodo->dtDue().dateTime().addSecs( utcOffSet ),
2482 d->mCalendar->timeSpec() );
2483 aTodo->setDtDue( dtDue );
2486 Todo::Ptr old = !aTodo->hasRecurrenceId() ?
2487 d->mCalendar->todo( aTodo->uid() ) :
2488 d->mCalendar->todo( aTodo->uid(), aTodo->recurrenceId() );
2491 d->mCalendar->deleteTodo( old );
2492 removeAllVCal( d->mTodosRelate, old );
2493 }
else if ( aTodo->revision() > old->revision() ) {
2494 d->mCalendar->deleteTodo( old );
2495 removeAllVCal( d->mTodosRelate, old );
2496 d->mCalendar->addTodo( aTodo );
2498 }
else if ( deleted ) {
2499 old = d->mCalendar->deletedTodo( aTodo->uid(), aTodo->recurrenceId() );
2501 d->mCalendar->addTodo( aTodo );
2502 d->mCalendar->deleteTodo( aTodo );
2505 d->mCalendar->addTodo( aTodo );
2508 }
else if ( ( strcmp( vObjectName( curVO ), VCVersionProp ) == 0 ) ||
2509 ( strcmp( vObjectName( curVO ), VCProdIdProp ) == 0 ) ||
2510 ( strcmp( vObjectName( curVO ), VCTimeZoneProp ) == 0 ) ) {
2514 }
else if ( strcmp( vObjectName( curVO ), VCDayLightProp ) == 0 ) {
2518 kDebug() <<
"Ignoring unknown vObject \"" << vObjectName(curVO) <<
"\"";
2525 Event::List::ConstIterator eIt;
2526 for ( eIt = d->mEventsRelate.constBegin(); eIt != d->mEventsRelate.constEnd(); ++eIt ) {
2527 (*eIt)->setRelatedTo( (*eIt)->relatedTo() );
2529 Todo::List::ConstIterator tIt;
2530 for ( tIt = d->mTodosRelate.constBegin(); tIt != d->mTodosRelate.constEnd(); ++tIt ) {
2531 (*tIt)->setRelatedTo( (*tIt)->relatedTo() );
2535 if ( hasTimeZone ) {
2536 d->mCalendar->setTimeSpec(previousSpec);
2543 const char *days[7] = {
"MO ",
"TU ",
"WE ",
"TH ",
"FR ",
"SA ",
"SU " };
2550 if ( day ==
"MO " ) {
2553 if ( day ==
"TU " ) {
2556 if ( day ==
"WE " ) {
2559 if ( day ==
"TH " ) {
2562 if ( day ==
"FR " ) {
2565 if ( day ==
"SA " ) {
2568 if ( day ==
"SU " ) {
2577 QString statStr = s;
2578 statStr = statStr.toUpper();
2581 if ( statStr ==
"X-ACTION" ) {
2583 }
else if ( statStr ==
"NEEDS ACTION" ) {
2585 }
else if ( statStr ==
"ACCEPTED" ) {
2587 }
else if ( statStr ==
"SENT" ) {
2589 }
else if ( statStr ==
"TENTATIVE" ) {
2591 }
else if ( statStr ==
"CONFIRMED" ) {
2593 }
else if ( statStr ==
"DECLINED" ) {
2595 }
else if ( statStr ==
"COMPLETED" ) {
2597 }
else if ( statStr ==
"DELEGATED" ) {
2600 kDebug() <<
"error setting attendee mStatus, unknown mStatus!";
2612 return "NEEDS ACTION";
2630 return "NEEDS ACTION";
2635 void VCalFormat::readCustomProperties( VObject *o,
const Incidence::Ptr &i )
2637 VObjectIterator iter;
2639 const char *curname;
2642 initPropIterator( &iter, o );
2643 while ( moreIteration( &iter ) ) {
2644 cur = nextVObject( &iter );
2645 curname = vObjectName( cur );
2646 Q_ASSERT( curname );
2647 if ( ( curname[0] ==
'X' && curname[1] ==
'-' ) &&
2648 strcmp( curname, ICOrganizerProp ) != 0 ) {
2651 i->setNonKDECustomProperty(
2652 curname, QString::fromUtf8( s = fakeCString( vObjectUStringZValue( cur ) ) ) );
2658 void VCalFormat::writeCustomProperties( VObject *o,
const Incidence::Ptr &i )
2660 const QMap<QByteArray, QString> custom = i->customProperties();
2661 for ( QMap<QByteArray, QString>::ConstIterator c = custom.begin();
2662 c != custom.end(); ++c ) {
2663 if ( d->mManuallyWrittenExtensionFields.contains( c.key() ) ) {
2667 addPropValue( o, c.key(), c.value().toUtf8() );