41 #include "icaltimezones.h"
43 #include "versit/vcc.h"
44 #include "versit/vobject.h"
49 #include <QtCore/QBitArray>
50 #include <QtCore/QFile>
51 #include <QTextDocument>
53 using namespace KCalCore;
61 void removeAllVCal( QVector< QSharedPointer<K> > &c,
const QSharedPointer<K> &x )
63 if ( c.count() < 1 ) {
67 int cnt = c.count( x );
69 qCritical() <<
"There number of relatedTos for this incidence is "
70 << cnt <<
" (there must be 1 relatedTo only)";
71 Q_ASSERT_X(
false,
"removeAllVCal",
"Count is not 1." );
75 c.remove( c.indexOf( x ) );
78 class KCalCore::VCalFormat::Private
84 QSet<QByteArray> mManuallyWrittenExtensionFields;
90 #if defined(KCALCORE_FOR_SYMBIAN)
91 d->mManuallyWrittenExtensionFields << VCRecurrenceIdProp;
92 d->mManuallyWrittenExtensionFields << EPOCAgendaEntryTypeProp;
94 d->mManuallyWrittenExtensionFields << KPilotIdProp;
95 d->mManuallyWrittenExtensionFields << KPilotStatusProp;
105 d->mCalendar = calendar;
113 vcal = Parse_MIME_FromFileName( const_cast<char *>( QFile::encodeName( fileName ).data() ) );
123 QString savedTimeZoneId = d->mCalendar->timeZoneId();
125 d->mCalendar->setTimeZoneId( savedTimeZoneId );
128 cleanVObjects( vcal );
136 d->mCalendar = calendar;
143 vcal = newVObject( VCCalProp );
146 addPropValue( vcal, VCProdIdProp,
productId().toLatin1() );
147 addPropValue( vcal, VCVersionProp, _VCAL_VERSION );
150 Todo::List todoList = d->mCalendar->rawTodos();
151 Todo::List::ConstIterator it;
152 for ( it = todoList.constBegin(); it != todoList.constEnd(); ++it ) {
153 if ( ( *it )->dtStart().timeZone().name().mid( 0, 4 ) ==
"VCAL" ) {
155 if ( zone.isValid() ) {
157 addPropValue( vcal, VCTimeZoneProp,
parseTZ( timezone ).toLocal8Bit() );
159 while ( !dst.isEmpty() ) {
160 addPropValue( vcal, VCDayLightProp, dst.toLocal8Bit() );
166 addVObjectProp( vcal, vo );
170 Event::List::ConstIterator it2;
171 for ( it2 = events.constBegin(); it2 != events.constEnd(); ++it2 ) {
172 if ( ( *it2 )->dtStart().timeZone().name().mid( 0, 4 ) ==
"VCAL" ) {
174 if ( zone.isValid() ) {
176 addPropValue( vcal, VCTimeZoneProp,
parseTZ( timezone ).toLocal8Bit() );
178 while ( !dst.isEmpty() ) {
179 addPropValue( vcal, VCDayLightProp, dst.toLocal8Bit() );
185 addVObjectProp( vcal, vo );
187 writeVObjectToFile( QFile::encodeName( fileName ).data(), vcal );
188 cleanVObjects( vcal );
191 if ( QFile::exists( fileName ) ) {
201 bool deleted,
const QString ¬ebook )
203 return fromRawString( calendar,
string.toUtf8(), deleted, notebook );
207 bool deleted,
const QString ¬ebook )
209 d->mCalendar = calendar;
211 if ( !
string.size() ) {
215 VObject *vcal = Parse_MIME(
string.data(),
string.size() );
221 initPropIterator( &i, vcal );
224 QString savedTimeZoneId = d->mCalendar->timeZoneId();
225 populate( vcal, deleted, notebook );
226 d->mCalendar->setTimeZoneId( savedTimeZoneId );
229 cleanVObjects( vcal );
236 const QString ¬ebook,
bool deleted )
239 d->mCalendar = calendar;
244 VObject *vcal = newVObject( VCCalProp );
247 addPropValue( vcal, VCVersionProp, _VCAL_VERSION );
250 Todo::List todoList = deleted ? d->mCalendar->deletedTodos() : d->mCalendar->rawTodos();
251 Todo::List::ConstIterator it;
252 for ( it = todoList.constBegin(); it != todoList.constEnd(); ++it ) {
253 if ( !deleted || !d->mCalendar->todo( ( *it )->uid(), ( *it )->recurrenceId() ) ) {
255 if ( notebook.isEmpty() ||
256 ( !calendar->notebook( *it ).isEmpty() &&
257 notebook.endsWith( calendar->notebook( *it ) ) ) ) {
258 if ( ( *it )->dtStart().timeZone().name().mid( 0, 4 ) ==
"VCAL" ) {
260 if ( zone.isValid() ) {
262 addPropValue( vcal, VCTimeZoneProp,
parseTZ( timezone ).toUtf8() );
264 while ( !dst.isEmpty() ) {
265 addPropValue( vcal, VCDayLightProp, dst.toUtf8() );
271 addVObjectProp( vcal, vo );
277 Event::List events = deleted ? d->mCalendar->deletedEvents() : d->mCalendar->rawEvents();
278 Event::List::ConstIterator it2;
279 for ( it2 = events.constBegin(); it2 != events.constEnd(); ++it2 ) {
280 if ( !deleted || !d->mCalendar->event( ( *it2 )->uid(), ( *it2 )->recurrenceId() ) ) {
282 if ( notebook.isEmpty() ||
283 ( !calendar->notebook( *it2 ).isEmpty() &&
284 notebook.endsWith( calendar->notebook( *it2 ) ) ) ) {
285 if ( ( *it2 )->dtStart().timeZone().name().mid( 0, 4 ) ==
"VCAL" ) {
287 if ( zone.isValid() ) {
289 addPropValue( vcal, VCTimeZoneProp,
parseTZ( timezone ).toUtf8() );
291 while ( !dst.isEmpty() ) {
292 addPropValue( vcal, VCDayLightProp, dst.toUtf8() );
298 addVObjectProp( vcal, vo );
303 char *buf = writeMemVObject( 0, 0, vcal );
305 QString result( QString::fromUtf8( buf ) );
309 cleanVObject( vcal );
319 vtodo = newVObject( VCTodoProp );
322 if ( anEvent->hasDueDate() ) {
324 addPropValue( vtodo, VCDueProp, tmpStr.toUtf8() );
328 if ( anEvent->hasStartDate() ) {
329 tmpStr =
kDateTimeToISO( anEvent->dtStart(), !anEvent->allDay() );
330 addPropValue( vtodo, VCDTstartProp, tmpStr.toUtf8() );
335 addPropValue( vtodo, VCDCreatedProp, tmpStr.toUtf8() );
338 addPropValue( vtodo, VCUniqueStringProp,
339 anEvent->uid().toUtf8() );
342 tmpStr.sprintf(
"%i", anEvent->revision() );
343 addPropValue( vtodo, VCSequenceProp, tmpStr.toUtf8() );
347 addPropValue( vtodo, VCLastModifiedProp, tmpStr.toUtf8() );
351 if ( !anEvent->organizer()->email().isEmpty() ) {
352 tmpStr =
"MAILTO:" + anEvent->organizer()->email();
353 addPropValue( vtodo, ICOrganizerProp, tmpStr.toUtf8() );
357 if ( anEvent->attendeeCount() > 0 ) {
358 Attendee::List::ConstIterator it;
360 for ( it = anEvent->attendees().constBegin(); it != anEvent->attendees().constEnd();
363 if ( !curAttendee->email().isEmpty() && !curAttendee->name().isEmpty() ) {
364 tmpStr =
"MAILTO:" + curAttendee->name() +
" <" + curAttendee->email() +
'>';
365 }
else if ( curAttendee->name().isEmpty() && curAttendee->email().isEmpty() ) {
367 kDebug() <<
"warning! this Event has an attendee w/o name or email!";
368 }
else if ( curAttendee->name().isEmpty() ) {
369 tmpStr =
"MAILTO: " + curAttendee->email();
371 tmpStr =
"MAILTO: " + curAttendee->name();
373 VObject *aProp = addPropValue( vtodo, VCAttendeeProp, tmpStr.toUtf8() );
374 addPropValue( aProp, VCRSVPProp, curAttendee->RSVP() ?
"TRUE" :
"FALSE" );
375 addPropValue( aProp, VCStatusProp,
writeStatus( curAttendee->status() ) );
380 const Recurrence *recur = anEvent->recurrence();
382 bool validRecur =
true;
385 case Recurrence::rDaily:
386 tmpStr.sprintf(
"D%i ", recur->
frequency() );
388 case Recurrence::rWeekly:
389 tmpStr.sprintf(
"W%i ", recur->
frequency() );
390 for (
int i = 0; i < 7; ++i ) {
391 QBitArray days ( recur->
days() );
392 if ( days.testBit( i ) ) {
397 case Recurrence::rMonthlyPos:
399 tmpStr.sprintf(
"MP%i ", recur->
frequency() );
401 QList<RecurrenceRule::WDayPos> tmpPositions = recur->
monthPositions();
402 for ( QList<RecurrenceRule::WDayPos>::ConstIterator posit = tmpPositions.constBegin();
403 posit != tmpPositions.constEnd(); ++posit ) {
404 int pos = (*posit).pos();
405 tmpStr2.sprintf(
"%i", ( pos > 0 ) ? pos : (-pos) );
416 case Recurrence::rMonthlyDay:
418 tmpStr.sprintf(
"MD%i ", recur->
frequency() );
420 const QList<int> tmpDays = recur->
monthDays();
421 for ( QList<int>::ConstIterator tmpDay = tmpDays.constBegin();
422 tmpDay != tmpDays.constEnd(); ++tmpDay ) {
423 tmpStr2.sprintf(
"%i ", *tmpDay );
428 case Recurrence::rYearlyMonth:
430 tmpStr.sprintf(
"YM%i ", recur->
frequency() );
433 const QList<int> months = recur->
yearMonths();
434 for ( QList<int>::ConstIterator mit = months.constBegin();
435 mit != months.constEnd(); ++mit ) {
436 tmpStr2.sprintf(
"%i ", *mit );
441 case Recurrence::rYearlyDay:
443 tmpStr.sprintf(
"YD%i ", recur->
frequency() );
445 const QList<int> tmpDays = recur->
yearDays();
446 for ( QList<int>::ConstIterator tmpDay = tmpDays.begin();
447 tmpDay != tmpDays.end(); ++tmpDay ) {
448 tmpStr2.sprintf(
"%i ", *tmpDay );
455 kDebug() <<
"ERROR, it should never get here in eventToVTodo!";
461 tmpStr2.sprintf(
"#%i", recur->
duration() );
463 }
else if ( recur->
duration() == -1 ) {
471 addPropValue( vtodo, VCRRuleProp, tmpStr.toUtf8() );
477 DateList dateList = recur->exDates();
478 DateList::ConstIterator id;
481 for (
id = dateList.constBegin();
id != dateList.constEnd(); ++id ) {
485 if ( !tmpStr2.isEmpty() ) {
486 tmpStr2.truncate( tmpStr2.length() - 1 );
487 addPropValue( vtodo, VCExpDateProp, tmpStr2.toUtf8() );
491 DateTimeList::ConstIterator idt;
494 for ( idt = dateTimeList.constBegin(); idt != dateTimeList.constEnd(); ++idt ) {
498 if ( !tmpStr2.isEmpty() ) {
499 tmpStr2.truncate( tmpStr2.length() - 1 );
500 addPropValue( vtodo, VCExpDateProp, tmpStr2.toUtf8() );
504 if ( !anEvent->description().isEmpty() ) {
505 QByteArray in = anEvent->description().toUtf8();
507 KCodecs::quotedPrintableEncode( in, out,
true );
509 VObject *d = addPropValue( vtodo, VCDescriptionProp, out );
510 addPropValue( d, VCEncodingProp, VCQuotedPrintableProp );
511 addPropValue( d, VCCharSetProp, VCUtf8Prop );
513 addPropValue( vtodo, VCDescriptionProp, in );
518 if ( !anEvent->summary().isEmpty() ) {
519 QByteArray in = anEvent->summary().toUtf8();
521 KCodecs::quotedPrintableEncode( in, out,
true );
523 VObject *d = addPropValue( vtodo, VCSummaryProp, out );
524 addPropValue( d, VCEncodingProp, VCQuotedPrintableProp );
525 addPropValue( d, VCCharSetProp, VCUtf8Prop );
527 addPropValue( vtodo, VCSummaryProp, in );
532 if ( !anEvent->location().isEmpty() ) {
533 QByteArray in = anEvent->location().toUtf8();
535 KCodecs::quotedPrintableEncode( in, out,
true );
537 VObject *d = addPropValue( vtodo, VCLocationProp, out );
538 addPropValue( d, VCEncodingProp, VCQuotedPrintableProp );
539 addPropValue( d, VCCharSetProp, VCUtf8Prop );
541 addPropValue( vtodo, VCLocationProp, in );
547 addPropValue( vtodo, VCStatusProp, anEvent->isCompleted() ?
"COMPLETED" :
"NEEDS ACTION" );
550 if ( anEvent->hasCompletedDate() ) {
552 addPropValue( vtodo, VCCompletedProp, tmpStr.toUtf8() );
556 tmpStr.sprintf(
"%i", anEvent->priority() );
557 addPropValue( vtodo, VCPriorityProp, tmpStr.toUtf8() );
560 if ( !anEvent->relatedTo().isEmpty() ) {
561 addPropValue( vtodo, VCRelatedToProp,
562 anEvent->relatedTo().toUtf8() );
566 const char *text = 0;
567 switch ( anEvent->secrecy() ) {
575 text =
"CONFIDENTIAL";
579 addPropValue( vtodo, VCClassProp, text );
583 const QStringList tmpStrList = anEvent->categories();
586 QStringList::const_iterator its;
587 for ( its = tmpStrList.constBegin(); its != tmpStrList.constEnd(); ++its ) {
589 if ( catStr[0] ==
' ' ) {
590 tmpStr += catStr.mid( 1 );
599 if ( !tmpStr.isEmpty() ) {
600 tmpStr.truncate( tmpStr.length() - 1 );
601 addPropValue( vtodo, VCCategoriesProp, tmpStr.toUtf8() );
605 Alarm::List::ConstIterator it;
606 for ( it = anEvent->alarms().constBegin(); it != anEvent->alarms().constEnd(); ++it ) {
608 if ( alarm->enabled() ) {
611 a = addProp( vtodo, VCDAlarmProp );
613 addPropValue( a, VCRunTimeProp, tmpStr.toUtf8() );
614 addPropValue( a, VCRepeatCountProp,
"1" );
615 if ( alarm->text().isNull() ) {
616 addPropValue( a, VCDisplayStringProp,
"beep!" );
618 addPropValue( a, VCDisplayStringProp, alarm->text().toLatin1().data() );
621 a = addProp( vtodo, VCAAlarmProp );
623 addPropValue( a, VCRunTimeProp, tmpStr.toUtf8() );
624 addPropValue( a, VCRepeatCountProp,
"1" );
625 addPropValue( a, VCAudioContentProp, QFile::encodeName( alarm->audioFile() ) );
627 a = addProp( vtodo, VCPAlarmProp );
629 addPropValue( a, VCRunTimeProp, tmpStr.toUtf8() );
630 addPropValue( a, VCRepeatCountProp,
"1" );
631 addPropValue( a, VCProcedureNameProp, QFile::encodeName( alarm->programFile() ) );
636 QString pilotId = anEvent->nonKDECustomProperty( KPilotIdProp );
637 if ( !pilotId.isEmpty() ) {
639 addPropValue( vtodo, KPilotIdProp, pilotId.toUtf8() );
640 addPropValue( vtodo, KPilotStatusProp,
641 anEvent->nonKDECustomProperty( KPilotStatusProp ).toUtf8() );
643 #if defined(KCALCORE_FOR_SYMBIAN)
644 if ( anEvent->nonKDECustomProperty( EPOCAgendaEntryTypeProp ).isEmpty() ) {
647 addPropValue( vtodo, EPOCAgendaEntryTypeProp,
"TODO" );
650 writeCustomProperties( vtodo, anEvent );
661 vevent = newVObject( VCEventProp );
664 tmpStr =
kDateTimeToISO( anEvent->dtStart(), !anEvent->allDay() );
665 addPropValue( vevent, VCDTstartProp, tmpStr.toUtf8() );
667 #if !defined(KCALCORE_FOR_MEEGO)
670 if ( anEvent->dtStart() != anEvent->dtEnd() ) {
672 addPropValue( vevent, VCDTendProp, tmpStr.toUtf8() );
677 addPropValue( vevent, VCDTendProp, tmpStr.toUtf8() );
682 addPropValue( vevent, VCDCreatedProp, tmpStr.toUtf8() );
685 addPropValue( vevent, VCUniqueStringProp,
686 anEvent->uid().toUtf8() );
689 tmpStr.sprintf(
"%i", anEvent->revision() );
690 addPropValue( vevent, VCSequenceProp, tmpStr.toUtf8() );
694 addPropValue( vevent, VCLastModifiedProp, tmpStr.toUtf8() );
698 if ( !anEvent->organizer()->email().isEmpty() ) {
699 tmpStr =
"MAILTO:" + anEvent->organizer()->email();
700 addPropValue( vevent, ICOrganizerProp, tmpStr.toUtf8() );
704 if ( anEvent->attendeeCount() > 0 ) {
705 Attendee::List::ConstIterator it;
706 for ( it = anEvent->attendees().constBegin(); it != anEvent->attendees().constEnd();
709 if ( !curAttendee->email().isEmpty() && !curAttendee->name().isEmpty() ) {
710 tmpStr =
"MAILTO:" + curAttendee->name() +
" <" + curAttendee->email() +
'>';
711 }
else if ( curAttendee->name().isEmpty() && curAttendee->email().isEmpty() ) {
713 kDebug() <<
"warning! this Event has an attendee w/o name or email!";
714 }
else if ( curAttendee->name().isEmpty() ) {
715 tmpStr =
"MAILTO: " + curAttendee->email();
717 tmpStr =
"MAILTO: " + curAttendee->name();
719 VObject *aProp = addPropValue( vevent, VCAttendeeProp, tmpStr.toUtf8() );
720 addPropValue( aProp, VCRSVPProp, curAttendee->RSVP() ?
"TRUE" :
"FALSE" );
721 addPropValue( aProp, VCStatusProp,
writeStatus( curAttendee->status() ) );
726 const Recurrence *recur = anEvent->recurrence();
728 bool validRecur =
true;
731 case Recurrence::rDaily:
732 tmpStr.sprintf(
"D%i ", recur->
frequency() );
734 case Recurrence::rWeekly:
735 tmpStr.sprintf(
"W%i ", recur->
frequency() );
736 for (
int i = 0; i < 7; ++i ) {
737 QBitArray days ( recur->
days() );
738 if ( days.testBit( i ) ) {
743 case Recurrence::rMonthlyPos:
745 tmpStr.sprintf(
"MP%i ", recur->
frequency() );
747 QList<RecurrenceRule::WDayPos> tmpPositions = recur->
monthPositions();
748 for ( QList<RecurrenceRule::WDayPos>::ConstIterator posit = tmpPositions.constBegin();
749 posit != tmpPositions.constEnd(); ++posit ) {
750 int pos = (*posit).pos();
751 tmpStr2.sprintf(
"%i", ( pos > 0 ) ? pos : (-pos) );
762 case Recurrence::rMonthlyDay:
764 tmpStr.sprintf(
"MD%i ", recur->
frequency() );
766 const QList<int> tmpDays = recur->
monthDays();
767 for ( QList<int>::ConstIterator tmpDay = tmpDays.constBegin();
768 tmpDay != tmpDays.constEnd(); ++tmpDay ) {
769 tmpStr2.sprintf(
"%i ", *tmpDay );
774 case Recurrence::rYearlyMonth:
776 tmpStr.sprintf(
"YM%i ", recur->
frequency() );
779 const QList<int> months = recur->
yearMonths();
780 for ( QList<int>::ConstIterator mit = months.constBegin();
781 mit != months.constEnd(); ++mit ) {
782 tmpStr2.sprintf(
"%i ", *mit );
787 case Recurrence::rYearlyDay:
789 tmpStr.sprintf(
"YD%i ", recur->
frequency() );
791 const QList<int> tmpDays = recur->
yearDays();
792 for ( QList<int>::ConstIterator tmpDay = tmpDays.begin();
793 tmpDay != tmpDays.end(); ++tmpDay ) {
794 tmpStr2.sprintf(
"%i ", *tmpDay );
801 kDebug() <<
"ERROR, it should never get here in eventToVEvent!";
807 tmpStr2.sprintf(
"#%i", recur->
duration() );
809 }
else if ( recur->
duration() == -1 ) {
812 #if !defined(KCALCORE_FOR_MEEGO)
822 addPropValue( vevent, VCRRuleProp, tmpStr.toUtf8() );
828 DateList dateList = recur->exDates();
829 DateList::ConstIterator it;
832 for ( it = dateList.constBegin(); it != dateList.constEnd(); ++it ) {
836 if ( !tmpStr2.isEmpty() ) {
837 tmpStr2.truncate( tmpStr2.length() - 1 );
838 addPropValue( vevent, VCExpDateProp, tmpStr2.toUtf8() );
842 DateTimeList::ConstIterator idt;
845 for ( idt = dateTimeList.constBegin(); idt != dateTimeList.constEnd(); ++idt ) {
849 if ( !tmpStr2.isEmpty() ) {
850 tmpStr2.truncate( tmpStr2.length() - 1 );
851 addPropValue( vevent, VCExpDateProp, tmpStr2.toUtf8() );
855 if ( !anEvent->description().isEmpty() ) {
856 QByteArray in = anEvent->description().toUtf8();
858 KCodecs::quotedPrintableEncode( in, out,
true );
860 VObject *d = addPropValue( vevent, VCDescriptionProp, out );
861 addPropValue( d, VCEncodingProp, VCQuotedPrintableProp );
862 addPropValue( d, VCCharSetProp, VCUtf8Prop );
864 addPropValue( vevent, VCDescriptionProp, in );
869 if ( !anEvent->summary().isEmpty() ) {
870 QByteArray in = anEvent->summary().toUtf8();
872 KCodecs::quotedPrintableEncode( in, out,
true );
874 VObject *d = addPropValue( vevent, VCSummaryProp, out );
875 addPropValue( d, VCEncodingProp, VCQuotedPrintableProp );
876 addPropValue( d, VCCharSetProp, VCUtf8Prop );
878 addPropValue( vevent, VCSummaryProp, in );
883 if ( !anEvent->location().isEmpty() ) {
884 QByteArray in = anEvent->location().toUtf8();
886 KCodecs::quotedPrintableEncode( in, out,
true );
888 VObject *d = addPropValue( vevent, VCLocationProp, out );
889 addPropValue( d, VCEncodingProp, VCQuotedPrintableProp );
890 addPropValue( d, VCCharSetProp, VCUtf8Prop );
892 addPropValue( vevent, VCLocationProp, in );
901 const char *text = 0;
902 switch ( anEvent->secrecy() ) {
910 text =
"CONFIDENTIAL";
914 addPropValue( vevent, VCClassProp, text );
918 QStringList tmpStrList = anEvent->categories();
921 for ( QStringList::const_iterator it = tmpStrList.constBegin(); it != tmpStrList.constEnd();
924 if ( catStr[0] ==
' ' ) {
925 tmpStr += catStr.mid( 1 );
934 if ( !tmpStr.isEmpty() ) {
935 tmpStr.truncate( tmpStr.length() - 1 );
936 addPropValue( vevent, VCCategoriesProp, tmpStr.toUtf8() );
942 Attachment::List::ConstIterator atIt;
943 for ( atIt = attachments.constBegin(); atIt != attachments.constEnd(); ++atIt ) {
944 addPropValue( vevent, VCAttachProp, ( *atIt )->uri().toUtf8() );
948 tmpStrList = anEvent->resources();
949 tmpStr = tmpStrList.join(
";" );
950 if ( !tmpStr.isEmpty() ) {
951 addPropValue( vevent, VCResourcesProp, tmpStr.toUtf8() );
955 Alarm::List::ConstIterator it2;
956 for ( it2 = anEvent->alarms().constBegin(); it2 != anEvent->alarms().constEnd(); ++it2 ) {
958 if ( alarm->enabled() ) {
961 a = addProp( vevent, VCDAlarmProp );
963 addPropValue( a, VCRunTimeProp, tmpStr.toUtf8() );
964 addPropValue( a, VCRepeatCountProp,
"1" );
965 if ( alarm->text().isNull() ) {
966 addPropValue( a, VCDisplayStringProp,
"beep!" );
968 addPropValue( a, VCDisplayStringProp, alarm->text().toLatin1().data() );
971 a = addProp( vevent, VCAAlarmProp );
973 addPropValue( a, VCRunTimeProp, tmpStr.toUtf8() );
974 addPropValue( a, VCRepeatCountProp,
"1" );
975 addPropValue( a, VCAudioContentProp, QFile::encodeName( alarm->audioFile() ) );
978 a = addProp( vevent, VCPAlarmProp );
980 addPropValue( a, VCRunTimeProp, tmpStr.toUtf8() );
981 addPropValue( a, VCRepeatCountProp,
"1" );
982 addPropValue( a, VCProcedureNameProp, QFile::encodeName( alarm->programFile() ) );
988 tmpStr.sprintf(
"%i", anEvent->priority() );
989 addPropValue( vevent, VCPriorityProp, tmpStr.toUtf8() );
992 tmpStr.sprintf(
"%i", anEvent->transparency() );
993 addPropValue( vevent, VCTranspProp, tmpStr.toUtf8() );
996 if ( !anEvent->relatedTo().isEmpty() ) {
997 addPropValue( vevent, VCRelatedToProp, anEvent->relatedTo().toUtf8() );
1000 QString pilotId = anEvent->nonKDECustomProperty( KPilotIdProp );
1001 if ( !pilotId.isEmpty() ) {
1003 addPropValue( vevent, KPilotIdProp, pilotId.toUtf8() );
1004 addPropValue( vevent, KPilotStatusProp,
1005 anEvent->nonKDECustomProperty( KPilotStatusProp ).toUtf8() );
1008 #if defined(KCALCORE_FOR_SYMBIAN)
1009 if ( anEvent->nonKDECustomProperty( EPOCAgendaEntryTypeProp ).isEmpty() ) {
1012 if ( anEvent->allDay() ) {
1013 addPropValue( vevent, EPOCAgendaEntryTypeProp,
"EVENT" );
1015 addPropValue( vevent, EPOCAgendaEntryTypeProp,
"APPOINTMENT" );
1019 if ( anEvent->hasRecurrenceId() ) {
1021 addPropValue( vevent, VCRecurrenceIdProp, tmpStr.toUtf8() );
1023 writeCustomProperties( vevent, anEvent );
1032 VObjectIterator voi;
1038 if ( ( vo = isAPropertyOf( vtodo, VCDCreatedProp ) ) != 0 ) {
1039 anEvent->setCreated(
ISOToKDateTime( s = fakeCString( vObjectUStringZValue( vo ) ) ) );
1044 vo = isAPropertyOf( vtodo, VCUniqueStringProp );
1048 anEvent->setUid( s = fakeCString( vObjectUStringZValue( vo ) ) );
1053 if ( ( vo = isAPropertyOf( vtodo, VCLastModifiedProp ) ) != 0 ) {
1054 anEvent->setLastModified(
ISOToKDateTime( s = fakeCString( vObjectUStringZValue( vo ) ) ) );
1057 anEvent->setLastModified( KDateTime::currentUtcDateTime() );
1062 if ( ( vo = isAPropertyOf( vtodo, ICOrganizerProp ) ) != 0 ) {
1063 anEvent->setOrganizer( s = fakeCString( vObjectUStringZValue( vo ) ) );
1066 if ( d->mCalendar->owner()->name() !=
"Unknown Name" ) {
1067 anEvent->setOrganizer( d->mCalendar->owner() );
1072 initPropIterator( &voi, vtodo );
1073 while ( moreIteration( &voi ) ) {
1074 vo = nextVObject( &voi );
1075 if ( strcmp( vObjectName( vo ), VCAttendeeProp ) == 0 ) {
1078 s = fakeCString( vObjectUStringZValue( vo ) );
1079 QString tmpStr = QString::fromUtf8( s );
1081 tmpStr = tmpStr.simplified();
1082 int emailPos1, emailPos2;
1083 if ( ( emailPos1 = tmpStr.indexOf(
'<' ) ) > 0 ) {
1085 emailPos2 = tmpStr.lastIndexOf(
'>' );
1087 tmpStr.mid( emailPos1 + 1,
1088 emailPos2 - ( emailPos1 + 1 ) ) ) );
1089 }
else if ( tmpStr.indexOf(
'@' ) > 0 ) {
1095 QString email = tmpStr.replace(
' ',
'.' );
1100 if ( ( vp = isAPropertyOf( vo, VCRSVPProp ) ) != 0 ) {
1101 a->setRSVP( vObjectStringZValue( vp ) );
1104 if ( ( vp = isAPropertyOf( vo, VCStatusProp ) ) != 0 ) {
1105 a->setStatus(
readStatus( vObjectStringZValue( vp ) ) );
1108 anEvent->addAttendee( a );
1113 if ( ( vo = isAPropertyOf( vtodo, VCDescriptionProp ) ) != 0 ) {
1114 s = fakeCString( vObjectUStringZValue( vo ) );
1115 anEvent->setDescription( QString::fromUtf8( s ), Qt::mightBeRichText( s ) );
1120 if ( ( vo = isAPropertyOf( vtodo, VCSummaryProp ) ) ) {
1121 s = fakeCString( vObjectUStringZValue( vo ) );
1122 anEvent->setSummary( QString::fromUtf8( s ), Qt::mightBeRichText( s ) );
1127 if ( ( vo = isAPropertyOf( vtodo, VCLocationProp ) ) != 0 ) {
1128 s = fakeCString( vObjectUStringZValue( vo ) );
1129 anEvent->setLocation( QString::fromUtf8( s ), Qt::mightBeRichText( s ) );
1135 if ( ( vo = isAPropertyOf( vtodo, VCStatusProp ) ) != 0 ) {
1136 s = fakeCString( vObjectUStringZValue( vo ) );
1137 if ( s && strcmp( s,
"COMPLETED" ) == 0 ) {
1138 anEvent->setCompleted(
true );
1140 anEvent->setCompleted(
false );
1144 anEvent->setCompleted(
false );
1148 if ( ( vo = isAPropertyOf( vtodo, VCCompletedProp ) ) != 0 ) {
1149 anEvent->setCompleted(
ISOToKDateTime( s = fakeCString( vObjectUStringZValue( vo ) ) ) );
1154 if ( ( vo = isAPropertyOf( vtodo, VCPriorityProp ) ) ) {
1155 s = fakeCString( vObjectUStringZValue( vo ) );
1157 anEvent->setPriority( atoi( s ) );
1162 anEvent->setAllDay(
false );
1165 if ( ( vo = isAPropertyOf( vtodo, VCDueProp ) ) != 0 ) {
1166 anEvent->setDtDue(
ISOToKDateTime( s = fakeCString( vObjectUStringZValue( vo ) ) ) );
1168 anEvent->setHasDueDate(
true );
1169 if ( anEvent->dtDue().time().hour() == 0 &&
1170 anEvent->dtDue().time().minute() == 0 &&
1171 anEvent->dtDue().time().second() == 0 ) {
1172 #if defined(KCALCORE_FOR_MEEGO)
1173 QDate dueDate = anEvent->dtDue().date();
1174 anEvent->setDtDue( KDateTime( dueDate, KDateTime::ClockTime ) );
1176 anEvent->setAllDay(
true );
1179 anEvent->setHasDueDate(
false );
1183 if ( ( vo = isAPropertyOf( vtodo, VCDTstartProp ) ) != 0 ) {
1184 anEvent->setDtStart(
ISOToKDateTime( s = fakeCString( vObjectUStringZValue( vo ) ) ) );
1186 anEvent->setHasStartDate(
true );
1187 if ( anEvent->dtStart().time().hour() == 0 &&
1188 anEvent->dtStart().time().minute() == 0 &&
1189 anEvent->dtStart().time().second() == 0 ) {
1190 #if defined(KCALCORE_FOR_MEEGO)
1191 QDate startDate = anEvent->dtStart().date();
1192 anEvent->setDtStart( KDateTime( startDate, KDateTime::ClockTime ) );
1194 anEvent->setAllDay(
true );
1197 anEvent->setHasStartDate(
false );
1201 if ( ( vo = isAPropertyOf( vtodo, VCRRuleProp ) ) != 0 ) {
1202 QString tmpStr = ( s = fakeCString( vObjectUStringZValue( vo ) ) );
1204 tmpStr.simplified();
1205 tmpStr = tmpStr.toUpper();
1208 uint type = Recurrence::rNone;
1209 if ( tmpStr.left( 1 ) ==
"D" ) {
1210 type = Recurrence::rDaily;
1211 }
else if ( tmpStr.left( 1 ) ==
"W" ) {
1212 type = Recurrence::rWeekly;
1215 if ( tmpStr.left( 2 ) ==
"MP" ) {
1216 type = Recurrence::rMonthlyPos;
1217 }
else if ( tmpStr.left( 2 ) ==
"MD" ) {
1218 type = Recurrence::rMonthlyDay;
1219 }
else if ( tmpStr.left( 2 ) ==
"YM" ) {
1220 type = Recurrence::rYearlyMonth;
1221 }
else if ( tmpStr.left( 2 ) ==
"YD" ) {
1222 type = Recurrence::rYearlyDay;
1226 if ( type != Recurrence::rNone ) {
1229 int index = tmpStr.indexOf(
' ' );
1230 int last = tmpStr.lastIndexOf(
' ' ) + 1;
1231 int rFreq = tmpStr.mid( typelen, ( index - 1 ) ).toInt();
1236 case Recurrence::rDaily:
1237 anEvent->recurrence()->setDaily( rFreq );
1240 case Recurrence::rWeekly:
1244 if ( index == last ) {
1246 qba.setBit( anEvent->dtStart().date().dayOfWeek() - 1 );
1249 while ( index < last ) {
1250 dayStr = tmpStr.mid( index, 3 );
1252 if ( dayNum >= 0 ) {
1253 qba.setBit( dayNum );
1258 anEvent->recurrence()->setWeekly( rFreq, qba );
1262 case Recurrence::rMonthlyPos:
1264 anEvent->recurrence()->setMonthly( rFreq );
1268 if ( index == last ) {
1270 tmpPos = anEvent->dtStart().date().day() / 7 + 1;
1271 if ( tmpPos == 5 ) {
1274 qba.setBit( anEvent->dtStart().date().dayOfWeek() - 1 );
1275 anEvent->recurrence()->addMonthlyPos( tmpPos, qba );
1278 while ( index < last ) {
1279 tmpPos = tmpStr.mid( index, 1 ).toShort();
1281 if ( tmpStr.mid( index, 1 ) ==
"-" ) {
1283 tmpPos = 0 - tmpPos;
1286 while (
numFromDay( tmpStr.mid( index, 3 ) ) >= 0 ) {
1287 int dayNum =
numFromDay( tmpStr.mid( index, 3 ) );
1288 qba.setBit( dayNum );
1291 anEvent->recurrence()->addMonthlyPos( tmpPos, qba );
1299 case Recurrence::rMonthlyDay:
1300 anEvent->recurrence()->setMonthly( rFreq );
1301 if ( index == last ) {
1303 short tmpDay = anEvent->dtStart().date().day();
1304 anEvent->recurrence()->addMonthlyDate( tmpDay );
1307 while ( index < last ) {
1308 int index2 = tmpStr.indexOf(
' ', index );
1309 if ( ( tmpStr.mid( ( index2 - 1 ), 1 ) ==
"-" ) ||
1310 ( tmpStr.mid( ( index2 - 1 ), 1 ) ==
"+" ) ) {
1311 index2 = index2 - 1;
1313 short tmpDay = tmpStr.mid( index, ( index2 - index ) ).toShort();
1315 if ( tmpStr.mid( index, 1 ) ==
"-" ) {
1316 tmpDay = 0 - tmpDay;
1319 anEvent->recurrence()->addMonthlyDate( tmpDay );
1324 case Recurrence::rYearlyMonth:
1325 anEvent->recurrence()->setYearly( rFreq );
1327 if ( index == last ) {
1329 short tmpMonth = anEvent->dtStart().date().month();
1330 anEvent->recurrence()->addYearlyMonth( tmpMonth );
1333 while ( index < last ) {
1334 int index2 = tmpStr.indexOf(
' ', index );
1335 short tmpMonth = tmpStr.mid( index, ( index2 - index ) ).toShort();
1337 anEvent->recurrence()->addYearlyMonth( tmpMonth );
1342 case Recurrence::rYearlyDay:
1343 anEvent->recurrence()->setYearly( rFreq );
1345 if ( index == last ) {
1347 short tmpDay = anEvent->dtStart().date().dayOfYear();
1348 anEvent->recurrence()->addYearlyDay( tmpDay );
1351 while ( index < last ) {
1352 int index2 = tmpStr.indexOf(
' ', index );
1353 short tmpDay = tmpStr.mid( index, ( index2 - index ) ).toShort();
1355 anEvent->recurrence()->addYearlyDay( tmpDay );
1366 if ( tmpStr.mid( index, 1 ) ==
"#" ) {
1369 int rDuration = tmpStr.mid( index, tmpStr.length() - index ).toInt();
1370 if ( rDuration > 0 ) {
1371 anEvent->recurrence()->setDuration( rDuration );
1373 }
else if ( tmpStr.indexOf(
'T', index ) != -1 ) {
1374 KDateTime rEndDate =
ISOToKDateTime( tmpStr.mid( index, tmpStr.length() - index ) );
1375 anEvent->recurrence()->setEndDateTime( rEndDate );
1378 kDebug() <<
"we don't understand this type of recurrence!";
1383 if ( ( vo = isAPropertyOf( vtodo, VCExpDateProp ) ) != 0 ) {
1384 s = fakeCString( vObjectUStringZValue( vo ) );
1385 QStringList exDates = QString::fromUtf8( s ).split(
',' );
1386 QStringList::ConstIterator it;
1387 for ( it = exDates.constBegin(); it != exDates.constEnd(); ++it ) {
1389 if ( exDate.time().hour() == 0 &&
1390 exDate.time().minute() == 0 &&
1391 exDate.time().second() == 0 ) {
1392 anEvent->recurrence()->addExDate(
ISOToQDate( *it ) );
1394 anEvent->recurrence()->addExDateTime( exDate );
1401 if ( ( vo = isAPropertyOf( vtodo, VCDAlarmProp ) ) ) {
1405 a = isAPropertyOf( vo, VCRunTimeProp );
1406 b = isAPropertyOf( vo, VCDisplayStringProp );
1409 alarm = anEvent->newAlarm();
1411 alarm->setTime(
ISOToKDateTime( s = fakeCString( vObjectUStringZValue( a ) ) ) );
1414 alarm->setEnabled(
true );
1416 s = fakeCString( vObjectUStringZValue( b ) );
1417 alarm->setDisplayAlarm( QString( s ) );
1420 alarm->setDisplayAlarm( QString() );
1425 if ( ( vo = isAPropertyOf( vtodo, VCAAlarmProp ) ) ) {
1429 a = isAPropertyOf( vo, VCRunTimeProp );
1430 b = isAPropertyOf( vo, VCAudioContentProp );
1433 alarm = anEvent->newAlarm();
1435 alarm->setTime(
ISOToKDateTime( s = fakeCString( vObjectUStringZValue( a ) ) ) );
1438 alarm->setEnabled(
true );
1440 s = fakeCString( vObjectUStringZValue( b ) );
1441 alarm->setAudioAlarm( QFile::decodeName( s ) );
1444 alarm->setAudioAlarm( QString() );
1449 if ( ( vo = isAPropertyOf( vtodo, VCPAlarmProp ) ) ) {
1453 a = isAPropertyOf( vo, VCRunTimeProp );
1454 b = isAPropertyOf( vo, VCProcedureNameProp );
1457 alarm = anEvent->newAlarm();
1459 alarm->setTime(
ISOToKDateTime( s = fakeCString( vObjectUStringZValue( a ) ) ) );
1462 alarm->setEnabled(
true );
1465 s = fakeCString( vObjectUStringZValue( b ) );
1466 alarm->setProcedureAlarm( QFile::decodeName( s ) );
1469 alarm->setProcedureAlarm( QString() );
1475 if ( ( vo = isAPropertyOf( vtodo, VCRelatedToProp ) ) != 0 ) {
1476 anEvent->setRelatedTo( s = fakeCString( vObjectUStringZValue( vo ) ) );
1478 d->mTodosRelate.append( anEvent );
1483 if ( ( vo = isAPropertyOf( vtodo, VCClassProp ) ) != 0 ) {
1484 s = fakeCString( vObjectUStringZValue( vo ) );
1485 if ( s && strcmp( s,
"PRIVATE" ) == 0 ) {
1487 }
else if ( s && strcmp( s,
"CONFIDENTIAL" ) == 0 ) {
1492 anEvent->setSecrecy( secrecy );
1495 if ( ( vo = isAPropertyOf( vtodo, VCCategoriesProp ) ) != 0 ) {
1496 s = fakeCString( vObjectUStringZValue( vo ) );
1497 QString categories = QString::fromUtf8( s );
1499 QStringList tmpStrList = categories.split(
';' );
1500 anEvent->setCategories( tmpStrList );
1504 if ( ( vo = isAPropertyOf( vtodo, KPilotIdProp ) ) ) {
1505 anEvent->setNonKDECustomProperty(
1506 KPilotIdProp, QString::fromUtf8( s = fakeCString( vObjectUStringZValue( vo ) ) ) );
1508 if ( ( vo = isAPropertyOf( vtodo, KPilotStatusProp ) ) ) {
1509 anEvent->setNonKDECustomProperty(
1510 KPilotStatusProp, QString::fromUtf8( s = fakeCString( vObjectUStringZValue( vo ) ) ) );
1513 anEvent->setNonKDECustomProperty( KPilotStatusProp, QString::number(
int( SYNCMOD ) ) );
1523 VObjectIterator voi;
1529 if ( ( vo = isAPropertyOf( vevent, VCDCreatedProp ) ) != 0 ) {
1530 anEvent->setCreated(
ISOToKDateTime( s = fakeCString( vObjectUStringZValue( vo ) ) ) );
1535 vo = isAPropertyOf( vevent, VCUniqueStringProp );
1539 anEvent->setUid( s = fakeCString( vObjectUStringZValue( vo ) ) );
1543 #if defined(KCALCORE_FOR_SYMBIAN)
1545 vo = isAPropertyOf( vevent, VCRecurrenceIdProp );
1547 anEvent->setRecurrenceId(
ISOToKDateTime( s = fakeCString( vObjectUStringZValue( vo ) ) ) );
1554 anEvent->setRevision( 0 );
1555 if ( ( vo = isAPropertyOf( vevent, VCSequenceProp ) ) != 0 ) {
1556 s = fakeCString( vObjectUStringZValue( vo ) );
1558 anEvent->setRevision( atoi( s ) );
1564 if ( ( vo = isAPropertyOf( vevent, VCLastModifiedProp ) ) != 0 ) {
1565 anEvent->setLastModified(
ISOToKDateTime( s = fakeCString( vObjectUStringZValue( vo ) ) ) );
1568 anEvent->setLastModified( KDateTime::currentUtcDateTime() );
1573 if ( ( vo = isAPropertyOf( vevent, ICOrganizerProp ) ) != 0 ) {
1575 anEvent->setOrganizer( s = fakeCString( vObjectUStringZValue( vo ) ) );
1578 if ( d->mCalendar->owner()->name() !=
"Unknown Name" ) {
1579 anEvent->setOrganizer( d->mCalendar->owner() );
1584 initPropIterator( &voi, vevent );
1585 while ( moreIteration( &voi ) ) {
1586 vo = nextVObject( &voi );
1587 if ( strcmp( vObjectName( vo ), VCAttendeeProp ) == 0 ) {
1590 s = fakeCString( vObjectUStringZValue( vo ) );
1591 QString tmpStr = QString::fromUtf8( s );
1593 tmpStr = tmpStr.simplified();
1594 int emailPos1, emailPos2;
1595 if ( ( emailPos1 = tmpStr.indexOf(
'<' ) ) > 0 ) {
1597 emailPos2 = tmpStr.lastIndexOf(
'>' );
1599 tmpStr.mid( emailPos1 + 1,
1600 emailPos2 - ( emailPos1 + 1 ) ) ) );
1601 }
else if ( tmpStr.indexOf(
'@' ) > 0 ) {
1606 QString email = tmpStr.replace(
' ',
'.' );
1611 if ( ( vp = isAPropertyOf( vo, VCRSVPProp ) ) != 0 ) {
1612 a->setRSVP( vObjectStringZValue( vp ) );
1615 if ( ( vp = isAPropertyOf( vo, VCStatusProp ) ) != 0 ) {
1616 a->setStatus(
readStatus( vObjectStringZValue( vp ) ) );
1619 anEvent->addAttendee( a );
1632 anEvent->setAllDay(
false );
1635 if ( ( vo = isAPropertyOf( vevent, VCDTstartProp ) ) != 0 ) {
1636 anEvent->setDtStart(
ISOToKDateTime( s = fakeCString( vObjectUStringZValue( vo ) ) ) );
1639 if ( anEvent->dtStart().time().hour() == 0 &&
1640 anEvent->dtStart().time().minute() == 0 &&
1641 anEvent->dtStart().time().second() == 0 ) {
1642 #if defined(KCALCORE_FOR_MEEGO)
1643 QDate startDate = anEvent->dtStart().date();
1644 anEvent->setDtStart( KDateTime( startDate, KDateTime::ClockTime ) );
1646 anEvent->setAllDay(
true );
1651 if ( ( vo = isAPropertyOf( vevent, VCDTendProp ) ) != 0 ) {
1652 anEvent->setDtEnd(
ISOToKDateTime( s = fakeCString( vObjectUStringZValue( vo ) ) ) );
1655 if ( anEvent->dtEnd().time().hour() == 0 &&
1656 anEvent->dtEnd().time().minute() == 0 &&
1657 anEvent->dtEnd().time().second() == 0 ) {
1658 #if defined(KCALCORE_FOR_MEEGO)
1659 QDate endDate = anEvent->dtEnd().date();
1660 anEvent->setDtEnd( KDateTime( endDate, KDateTime::ClockTime ) );
1662 anEvent->setAllDay(
true );
1665 #if defined(KCALCORE_FOR_MEEGO)
1666 if ( anEvent->allDay() ) {
1667 if ( anEvent->dtEnd() == anEvent->dtStart() ) {
1668 anEvent->setDtEnd( anEvent->dtEnd().addDays( 1 ) );
1675 if ( !isAPropertyOf( vevent, VCDTstartProp ) ) {
1676 anEvent->setDtStart( anEvent->dtEnd() );
1678 if ( ! isAPropertyOf( vevent, VCDTendProp ) ) {
1679 anEvent->setDtEnd( anEvent->dtStart() );
1685 if ( ( vo = isAPropertyOf( vevent, VCRRuleProp ) ) != 0 ) {
1686 QString tmpStr = ( s = fakeCString( vObjectUStringZValue( vo ) ) );
1688 tmpStr.simplified();
1689 tmpStr = tmpStr.toUpper();
1692 uint type = Recurrence::rNone;
1693 if ( tmpStr.left( 1 ) ==
"D" ) {
1694 type = Recurrence::rDaily;
1695 }
else if ( tmpStr.left( 1 ) ==
"W" ) {
1696 type = Recurrence::rWeekly;
1699 if ( tmpStr.left( 2 ) ==
"MP" ) {
1700 type = Recurrence::rMonthlyPos;
1701 }
else if ( tmpStr.left( 2 ) ==
"MD" ) {
1702 type = Recurrence::rMonthlyDay;
1703 }
else if ( tmpStr.left( 2 ) ==
"YM" ) {
1704 type = Recurrence::rYearlyMonth;
1705 }
else if ( tmpStr.left( 2 ) ==
"YD" ) {
1706 type = Recurrence::rYearlyDay;
1710 if ( type != Recurrence::rNone ) {
1713 int index = tmpStr.indexOf(
' ' );
1714 int last = tmpStr.lastIndexOf(
' ' ) + 1;
1715 int rFreq = tmpStr.mid( typelen, ( index - 1 ) ).toInt();
1720 case Recurrence::rDaily:
1721 anEvent->recurrence()->setDaily( rFreq );
1724 case Recurrence::rWeekly:
1728 if ( index == last ) {
1730 qba.setBit( anEvent->dtStart().date().dayOfWeek() - 1 );
1733 while ( index < last ) {
1734 dayStr = tmpStr.mid( index, 3 );
1736 if ( dayNum >= 0 ) {
1737 qba.setBit( dayNum );
1742 anEvent->recurrence()->setWeekly( rFreq, qba );
1746 case Recurrence::rMonthlyPos:
1748 anEvent->recurrence()->setMonthly( rFreq );
1752 if ( index == last ) {
1754 tmpPos = anEvent->dtStart().date().day() / 7 + 1;
1755 if ( tmpPos == 5 ) {
1758 qba.setBit( anEvent->dtStart().date().dayOfWeek() - 1 );
1759 anEvent->recurrence()->addMonthlyPos( tmpPos, qba );
1762 while ( index < last ) {
1763 tmpPos = tmpStr.mid( index, 1 ).toShort();
1765 if ( tmpStr.mid( index, 1 ) ==
"-" ) {
1767 tmpPos = 0 - tmpPos;
1770 while (
numFromDay( tmpStr.mid( index, 3 ) ) >= 0 ) {
1771 int dayNum =
numFromDay( tmpStr.mid( index, 3 ) );
1772 qba.setBit( dayNum );
1775 anEvent->recurrence()->addMonthlyPos( tmpPos, qba );
1783 case Recurrence::rMonthlyDay:
1784 anEvent->recurrence()->setMonthly( rFreq );
1785 if ( index == last ) {
1787 short tmpDay = anEvent->dtStart().date().day();
1788 anEvent->recurrence()->addMonthlyDate( tmpDay );
1791 while ( index < last ) {
1792 int index2 = tmpStr.indexOf(
' ', index );
1793 if ( ( tmpStr.mid( ( index2 - 1 ), 1 ) ==
"-" ) ||
1794 ( tmpStr.mid( ( index2 - 1 ), 1 ) ==
"+" ) ) {
1795 index2 = index2 - 1;
1797 short tmpDay = tmpStr.mid( index, ( index2 - index ) ).toShort();
1799 if ( tmpStr.mid( index, 1 ) ==
"-" ) {
1800 tmpDay = 0 - tmpDay;
1803 anEvent->recurrence()->addMonthlyDate( tmpDay );
1808 case Recurrence::rYearlyMonth:
1809 anEvent->recurrence()->setYearly( rFreq );
1811 if ( index == last ) {
1813 short tmpMonth = anEvent->dtStart().date().month();
1814 anEvent->recurrence()->addYearlyMonth( tmpMonth );
1817 while ( index < last ) {
1818 int index2 = tmpStr.indexOf(
' ', index );
1819 short tmpMonth = tmpStr.mid( index, ( index2 - index ) ).toShort();
1821 anEvent->recurrence()->addYearlyMonth( tmpMonth );
1826 case Recurrence::rYearlyDay:
1827 anEvent->recurrence()->setYearly( rFreq );
1829 if ( index == last ) {
1831 short tmpDay = anEvent->dtStart().date().dayOfYear();
1832 anEvent->recurrence()->addYearlyDay( tmpDay );
1835 while ( index < last ) {
1836 int index2 = tmpStr.indexOf(
' ', index );
1837 short tmpDay = tmpStr.mid( index, ( index2 - index ) ).toShort();
1839 anEvent->recurrence()->addYearlyDay( tmpDay );
1850 if ( tmpStr.mid( index, 1 ) ==
"#" ) {
1853 int rDuration = tmpStr.mid( index, tmpStr.length() - index ).toInt();
1854 if ( rDuration > 0 ) {
1855 anEvent->recurrence()->setDuration( rDuration );
1857 }
else if ( tmpStr.indexOf(
'T', index ) != -1 ) {
1858 KDateTime rEndDate =
ISOToKDateTime( tmpStr.mid( index, tmpStr.length() - index ) );
1859 anEvent->recurrence()->setEndDateTime( rEndDate );
1864 kDebug() <<
"we don't understand this type of recurrence!";
1869 if ( ( vo = isAPropertyOf( vevent, VCExpDateProp ) ) != 0 ) {
1870 s = fakeCString( vObjectUStringZValue( vo ) );
1871 QStringList exDates = QString::fromUtf8( s ).split(
',' );
1872 QStringList::ConstIterator it;
1873 for ( it = exDates.constBegin(); it != exDates.constEnd(); ++it ) {
1875 if ( exDate.time().hour() == 0 &&
1876 exDate.time().minute() == 0 &&
1877 exDate.time().second() == 0 ) {
1878 anEvent->recurrence()->addExDate(
ISOToQDate( *it ) );
1880 anEvent->recurrence()->addExDateTime( exDate );
1887 if ( ( vo = isAPropertyOf( vevent, VCSummaryProp ) ) ) {
1888 s = fakeCString( vObjectUStringZValue( vo ) );
1889 anEvent->setSummary( QString::fromUtf8( s ), Qt::mightBeRichText( s ) );
1894 if ( ( vo = isAPropertyOf( vevent, VCDescriptionProp ) ) != 0 ) {
1895 s = fakeCString( vObjectUStringZValue( vo ) );
1896 bool isRich = Qt::mightBeRichText( s );
1897 if ( !anEvent->description().isEmpty() ) {
1898 anEvent->setDescription(
1899 anEvent->description() +
'\n' + QString::fromUtf8( s ), isRich );
1901 anEvent->setDescription( QString::fromUtf8( s ), isRich );
1907 if ( ( vo = isAPropertyOf( vevent, VCLocationProp ) ) != 0 ) {
1908 s = fakeCString( vObjectUStringZValue( vo ) );
1909 anEvent->setLocation( QString::fromUtf8( s ), Qt::mightBeRichText( s ) );
1915 if ( anEvent->summary().isEmpty() && !( anEvent->description().isEmpty() ) ) {
1916 QString tmpStr = anEvent->description().simplified();
1917 anEvent->setDescription(
"" );
1918 anEvent->setSummary( tmpStr );
1923 if ( ( vo = isAPropertyOf( vevent, VCStatusProp ) ) != 0 ) {
1924 QString tmpStr( s = fakeCString( vObjectUStringZValue( vo ) ) );
1935 if ( ( vo = isAPropertyOf( vevent, VCClassProp ) ) != 0 ) {
1936 s = fakeCString( vObjectUStringZValue( vo ) );
1937 if ( s && strcmp( s,
"PRIVATE" ) == 0 ) {
1939 }
else if ( s && strcmp( s,
"CONFIDENTIAL" ) == 0 ) {
1944 anEvent->setSecrecy( secrecy );
1947 if ( ( vo = isAPropertyOf( vevent, VCCategoriesProp ) ) != 0 ) {
1948 s = fakeCString( vObjectUStringZValue( vo ) );
1949 QString categories = QString::fromUtf8( s );
1951 QStringList tmpStrList = categories.split(
',' );
1952 anEvent->setCategories( tmpStrList );
1956 initPropIterator( &voi, vevent );
1957 while ( moreIteration( &voi ) ) {
1958 vo = nextVObject( &voi );
1959 if ( strcmp( vObjectName( vo ), VCAttachProp ) == 0 ) {
1960 s = fakeCString( vObjectUStringZValue( vo ) );
1967 if ( ( vo = isAPropertyOf( vevent, VCResourcesProp ) ) != 0 ) {
1968 QString resources = ( s = fakeCString( vObjectUStringZValue( vo ) ) );
1970 QStringList tmpStrList = resources.split(
';' );
1971 anEvent->setResources( tmpStrList );
1975 if ( ( vo = isAPropertyOf( vevent, VCDAlarmProp ) ) ) {
1979 a = isAPropertyOf( vo, VCRunTimeProp );
1980 b = isAPropertyOf( vo, VCDisplayStringProp );
1983 alarm = anEvent->newAlarm();
1985 alarm->setTime(
ISOToKDateTime( s = fakeCString( vObjectUStringZValue( a ) ) ) );
1988 alarm->setEnabled(
true );
1991 s = fakeCString( vObjectUStringZValue( b ) );
1992 alarm->setDisplayAlarm( QString( s ) );
1995 alarm->setDisplayAlarm( QString() );
2000 if ( ( vo = isAPropertyOf( vevent, VCAAlarmProp ) ) ) {
2004 a = isAPropertyOf( vo, VCRunTimeProp );
2005 b = isAPropertyOf( vo, VCAudioContentProp );
2008 alarm = anEvent->newAlarm();
2010 alarm->setTime(
ISOToKDateTime( s = fakeCString( vObjectUStringZValue( a ) ) ) );
2013 alarm->setEnabled(
true );
2016 s = fakeCString( vObjectUStringZValue( b ) );
2017 alarm->setAudioAlarm( QFile::decodeName( s ) );
2020 alarm->setAudioAlarm( QString() );
2025 if ( ( vo = isAPropertyOf( vevent, VCPAlarmProp ) ) ) {
2029 a = isAPropertyOf( vo, VCRunTimeProp );
2030 b = isAPropertyOf( vo, VCProcedureNameProp );
2033 alarm = anEvent->newAlarm();
2035 alarm->setTime(
ISOToKDateTime( s = fakeCString( vObjectUStringZValue( a ) ) ) );
2038 alarm->setEnabled(
true );
2041 s = fakeCString( vObjectUStringZValue( b ) );
2042 alarm->setProcedureAlarm( QFile::decodeName( s ) );
2045 alarm->setProcedureAlarm( QString() );
2051 if ( ( vo = isAPropertyOf( vevent, VCPriorityProp ) ) ) {
2052 s = fakeCString( vObjectUStringZValue( vo ) );
2054 anEvent->setPriority( atoi( s ) );
2060 if ( ( vo = isAPropertyOf( vevent, VCTranspProp ) ) != 0 ) {
2061 s = fakeCString( vObjectUStringZValue( vo ) );
2070 if ( ( vo = isAPropertyOf( vevent, VCRelatedToProp ) ) != 0 ) {
2071 anEvent->setRelatedTo( s = fakeCString( vObjectUStringZValue( vo ) ) );
2073 d->mEventsRelate.append( anEvent );
2077 if ( ( vo = isAPropertyOf( vevent, KPilotIdProp ) ) ) {
2078 anEvent->setNonKDECustomProperty(
2079 KPilotIdProp, QString::fromUtf8( s = fakeCString( vObjectUStringZValue( vo ) ) ) );
2081 if ( ( vo = isAPropertyOf( vevent, KPilotStatusProp ) ) ) {
2082 anEvent->setNonKDECustomProperty(
2083 KPilotStatusProp, QString::fromUtf8( s = fakeCString( vObjectUStringZValue( vo ) ) ) );
2086 anEvent->setNonKDECustomProperty( KPilotStatusProp, QString::number(
int( SYNCMOD ) ) );
2091 readCustomProperties( vevent, anEvent );
2099 QString pZone = timezone.mid( timezone.indexOf(
"TZID:VCAL" ) + 9 );
2100 return pZone.mid( 0, pZone.indexOf( QChar( QLatin1Char(
'\n' ) ) ) );
2105 if ( !timezone.contains(
"BEGIN:DAYLIGHT" ) ) {
2109 timezone = timezone.mid( timezone.indexOf(
"BEGIN:DAYLIGHT" ) );
2110 timezone = timezone.mid( timezone.indexOf(
"TZNAME:" ) + 7 );
2111 QString sStart = timezone.mid( 0, ( timezone.indexOf(
"COMMENT:" ) ) );
2113 timezone = timezone.mid( timezone.indexOf(
"TZOFFSETTO:" ) + 11 );
2114 QString sOffset = timezone.mid( 0, ( timezone.indexOf(
"DTSTART:" ) ) );
2116 sOffset.insert( 3, QString(
":" ) );
2117 timezone = timezone.mid( timezone.indexOf(
"TZNAME:" ) + 7 );
2118 QString sEnd = timezone.mid( 0, ( timezone.indexOf(
"COMMENT:" ) ) );
2121 return "TRUE;" + sOffset +
';' + sStart +
';' + sEnd +
";;";
2128 if ( !qd.isValid() ) {
2132 tmpStr.sprintf(
"%.2d%.2d%.2d", qd.year(), qd.month(), qd.day() );
2141 if ( !dt.isValid() ) {
2147 tmpDT = dt.toUtc().dateTime();
2149 #if !defined(KCALCORE_FOR_MEEGO)
2150 tmpDT = dt.toTimeSpec( d->mCalendar->timeSpec() ).dateTime();
2152 tmpDT = dt.dateTime();
2155 tmpStr.sprintf(
"%.2d%.2d%.2dT%.2d%.2d%.2d",
2156 tmpDT.date().year(), tmpDT.date().month(),
2157 tmpDT.date().day(), tmpDT.time().hour(),
2158 tmpDT.time().minute(), tmpDT.time().second() );
2159 if ( zulu || dt.isUtc() ) {
2170 int year, month, day, hour, minute, second;
2173 year = tmpStr.left( 4 ).toInt();
2174 month = tmpStr.mid( 4, 2 ).toInt();
2175 day = tmpStr.mid( 6, 2 ).toInt();
2176 hour = tmpStr.mid( 9, 2 ).toInt();
2177 minute = tmpStr.mid( 11, 2 ).toInt();
2178 second = tmpStr.mid( 13, 2 ).toInt();
2179 tmpDate.setYMD( year, month, day );
2180 tmpTime.setHMS( hour, minute, second );
2182 if ( tmpDate.isValid() && tmpTime.isValid() ) {
2184 if ( dtStr.at( dtStr.length() - 1 ) ==
'Z' ) {
2185 return KDateTime( tmpDate, tmpTime, KDateTime::UTC );
2187 return KDateTime( tmpDate, tmpTime, d->mCalendar->timeSpec() );
2196 int year, month, day;
2198 year = dateStr.left( 4 ).toInt();
2199 month = dateStr.mid( 4, 2 ).toInt();
2200 day = dateStr.mid( 6, 2 ).toInt();
2202 return QDate( year, month, day );
2215 QString str = s.trimmed();
2220 if ( str.size() <= ofs ) {
2223 if ( str[ofs] ==
'-' ) {
2226 }
else if ( str[ofs] ==
'+' ) {
2229 if ( str.size() <= ofs ) {
2236 if ( str.size() < ( ofs + 2 ) ) {
2240 v = str.mid( ofs, 2 ).toInt( &ok ) * 60;
2246 if ( str.size() > ofs ) {
2247 if ( str[ofs] ==
':' ) {
2250 if ( str.size() > ofs ) {
2251 if ( str.size() < ( ofs + 2 ) ) {
2254 v += str.mid( ofs, 2 ).toInt( &ok );
2260 result = v * mod * 60;
2269 Q_UNUSED( notebook );
2274 VObject *curVO, *curVOProp;
2276 bool hasTimeZone =
false;
2277 KDateTime::Spec previousSpec;
2279 if ( ( curVO = isAPropertyOf( vcal, ICMethodProp ) ) != 0 ) {
2280 char *methodType = 0;
2281 methodType = fakeCString( vObjectUStringZValue( curVO ) );
2283 deleteStr( methodType );
2287 if ( ( curVO = isAPropertyOf( vcal, VCProdIdProp ) ) != 0 ) {
2288 char *s = fakeCString( vObjectUStringZValue( curVO ) );
2289 if ( !s || strcmp(
productId().toUtf8(), s ) != 0 ) {
2290 kDebug() <<
"This vCalendar file was not created by KOrganizer or"
2291 <<
"any other product we support. Loading anyway...";
2298 if ( ( curVO = isAPropertyOf( vcal, VCVersionProp ) ) != 0 ) {
2299 char *s = fakeCString( vObjectUStringZValue( curVO ) );
2300 if ( !s || strcmp( _VCAL_VERSION, s ) != 0 ) {
2301 kDebug() <<
"This vCalendar file has version" << s
2302 <<
"We only support" << _VCAL_VERSION;
2308 if ( ( curVO = isAPropertyOf( vcal, VCTimeZoneProp ) ) != 0 ) {
2309 char *s = fakeCString( vObjectUStringZValue( curVO ) );
2311 QString name =
"VCAL" + ts;
2327 KDateTime dt = KDateTime( QDateTime( QDate( 1900, 1, 1 ), QTime( 0, 0, 0 ) ) );
2328 tz = QString(
"STD;%1;false;%2" ).arg( QString::number( utcOffset ) ).arg( dt.toString() );
2329 tzList.append( tz );
2332 initPropIterator( &i, vcal );
2333 while ( moreIteration( &i ) ) {
2334 curVO = nextVObject( &i );
2335 if ( strcmp( vObjectName( curVO ), VCDayLightProp ) == 0 ) {
2336 char *s = fakeCString( vObjectUStringZValue( curVO ) );
2337 QString dst = QString( s );
2338 QStringList argl = dst.split(
',' );
2342 if ( argl.size() < 4 ) {
2347 if ( argl[0] !=
"TRUE" ) {
2355 QString strEndDate = argl[3];
2358 QString strStartDate = argl[2];
2361 QString strRealEndDate = strEndDate;
2362 QString strRealStartDate = strStartDate;
2363 KDateTime realEndDate = endDate;
2364 KDateTime realStartDate = startDate;
2366 if ( endDate < startDate ) {
2367 strRealEndDate = strStartDate;
2368 strRealStartDate = strEndDate;
2369 realEndDate = startDate;
2370 realStartDate = endDate;
2372 tz = QString(
"%1;%2;false;%3" ).
2373 arg( strRealEndDate ).
2374 arg( QString::number( utcOffset ) ).
2375 arg( realEndDate.toString() );
2376 tzList.append( tz );
2378 tz = QString(
"%1;%2;true;%3" ).
2379 arg( strRealStartDate ).
2380 arg( QString::number( utcOffsetDst ) ).
2381 arg( realStartDate.toString() );
2382 tzList.append( tz );
2384 kDebug() <<
"unable to parse dst" << argl[1];
2391 if ( !zone.isValid() ) {
2392 kDebug() <<
"zone is not valid, parsing error" << tzList;
2394 previousSpec = d->mCalendar->timeSpec();
2395 d->mCalendar->setTimeZoneId( name );
2399 kDebug() <<
"unable to parse tzoffset" << ts;
2404 d->mEventsRelate.clear();
2405 d->mTodosRelate.clear();
2407 initPropIterator( &i, vcal );
2410 while ( moreIteration( &i ) ) {
2411 curVO = nextVObject( &i );
2416 if ( strcmp( vObjectName( curVO ), VCEventProp ) == 0 ) {
2418 if ( ( curVOProp = isAPropertyOf( curVO, KPilotStatusProp ) ) != 0 ) {
2420 s = fakeCString( vObjectUStringZValue( curVOProp ) );
2423 if ( atoi( s ) == SYNCDEL ) {
2425 kDebug() <<
"skipping pilot-deleted event";
2432 if ( !isAPropertyOf( curVO, VCDTstartProp ) &&
2433 !isAPropertyOf( curVO, VCDTendProp ) ) {
2434 kDebug() <<
"found a VEvent with no DTSTART and no DTEND! Skipping...";
2440 if ( hasTimeZone && !anEvent->allDay() && anEvent->dtStart().isUtc() ) {
2445 int utcOffSet = anEvent->dtStart().utcOffset();
2446 KDateTime dtStart( anEvent->dtStart().dateTime().addSecs( utcOffSet ),
2447 d->mCalendar->timeSpec() );
2448 KDateTime dtEnd( anEvent->dtEnd().dateTime().addSecs( utcOffSet ),
2449 d->mCalendar->timeSpec() );
2450 anEvent->setDtStart( dtStart );
2451 anEvent->setDtEnd( dtEnd );
2453 Event::Ptr old = !anEvent->hasRecurrenceId() ?
2454 d->mCalendar->event( anEvent->uid() ) :
2455 d->mCalendar->event( anEvent->uid(), anEvent->recurrenceId() );
2459 d->mCalendar->deleteEvent( old );
2460 removeAllVCal( d->mEventsRelate, old );
2461 }
else if ( anEvent->revision() > old->revision() ) {
2462 d->mCalendar->deleteEvent( old );
2463 removeAllVCal( d->mEventsRelate, old );
2464 d->mCalendar->addEvent( anEvent );
2466 }
else if ( deleted ) {
2467 old = !anEvent->hasRecurrenceId() ?
2468 d->mCalendar->deletedEvent( anEvent->uid() ) :
2469 d->mCalendar->deletedEvent( anEvent->uid(), anEvent->recurrenceId() );
2471 d->mCalendar->addEvent( anEvent );
2472 d->mCalendar->deleteEvent( anEvent );
2475 d->mCalendar->addEvent( anEvent );
2478 }
else if ( strcmp( vObjectName( curVO ), VCTodoProp ) == 0 ) {
2481 if ( hasTimeZone && !aTodo->allDay() && aTodo->dtStart().isUtc() ) {
2486 int utcOffSet = aTodo->dtStart().utcOffset();
2487 KDateTime dtStart( aTodo->dtStart().dateTime().addSecs( utcOffSet ),
2488 d->mCalendar->timeSpec() );
2489 aTodo->setDtStart( dtStart );
2490 if ( aTodo->hasDueDate() ) {
2491 KDateTime dtDue( aTodo->dtDue().dateTime().addSecs( utcOffSet ),
2492 d->mCalendar->timeSpec() );
2493 aTodo->setDtDue( dtDue );
2496 Todo::Ptr old = !aTodo->hasRecurrenceId() ?
2497 d->mCalendar->todo( aTodo->uid() ) :
2498 d->mCalendar->todo( aTodo->uid(), aTodo->recurrenceId() );
2501 d->mCalendar->deleteTodo( old );
2502 removeAllVCal( d->mTodosRelate, old );
2503 }
else if ( aTodo->revision() > old->revision() ) {
2504 d->mCalendar->deleteTodo( old );
2505 removeAllVCal( d->mTodosRelate, old );
2506 d->mCalendar->addTodo( aTodo );
2508 }
else if ( deleted ) {
2509 old = d->mCalendar->deletedTodo( aTodo->uid(), aTodo->recurrenceId() );
2511 d->mCalendar->addTodo( aTodo );
2512 d->mCalendar->deleteTodo( aTodo );
2515 d->mCalendar->addTodo( aTodo );
2518 }
else if ( ( strcmp( vObjectName( curVO ), VCVersionProp ) == 0 ) ||
2519 ( strcmp( vObjectName( curVO ), VCProdIdProp ) == 0 ) ||
2520 ( strcmp( vObjectName( curVO ), VCTimeZoneProp ) == 0 ) ) {
2524 }
else if ( strcmp( vObjectName( curVO ), VCDayLightProp ) == 0 ) {
2528 kDebug() <<
"Ignoring unknown vObject \"" << vObjectName(curVO) <<
"\"";
2535 Event::List::ConstIterator eIt;
2536 for ( eIt = d->mEventsRelate.constBegin(); eIt != d->mEventsRelate.constEnd(); ++eIt ) {
2537 (*eIt)->setRelatedTo( (*eIt)->relatedTo() );
2539 Todo::List::ConstIterator tIt;
2540 for ( tIt = d->mTodosRelate.constBegin(); tIt != d->mTodosRelate.constEnd(); ++tIt ) {
2541 (*tIt)->setRelatedTo( (*tIt)->relatedTo() );
2545 if ( hasTimeZone ) {
2546 d->mCalendar->setTimeSpec(previousSpec);
2553 const char *days[7] = {
"MO ",
"TU ",
"WE ",
"TH ",
"FR ",
"SA ",
"SU " };
2560 if ( day ==
"MO " ) {
2563 if ( day ==
"TU " ) {
2566 if ( day ==
"WE " ) {
2569 if ( day ==
"TH " ) {
2572 if ( day ==
"FR " ) {
2575 if ( day ==
"SA " ) {
2578 if ( day ==
"SU " ) {
2587 QString statStr = s;
2588 statStr = statStr.toUpper();
2591 if ( statStr ==
"X-ACTION" ) {
2593 }
else if ( statStr ==
"NEEDS ACTION" ) {
2595 }
else if ( statStr ==
"ACCEPTED" ) {
2597 }
else if ( statStr ==
"SENT" ) {
2599 }
else if ( statStr ==
"TENTATIVE" ) {
2601 }
else if ( statStr ==
"CONFIRMED" ) {
2603 }
else if ( statStr ==
"DECLINED" ) {
2605 }
else if ( statStr ==
"COMPLETED" ) {
2607 }
else if ( statStr ==
"DELEGATED" ) {
2610 kDebug() <<
"error setting attendee mStatus, unknown mStatus!";
2622 return "NEEDS ACTION";
2640 return "NEEDS ACTION";
2645 void VCalFormat::readCustomProperties( VObject *o,
const Incidence::Ptr &i )
2647 VObjectIterator iter;
2649 const char *curname;
2652 initPropIterator( &iter, o );
2653 while ( moreIteration( &iter ) ) {
2654 cur = nextVObject( &iter );
2655 curname = vObjectName( cur );
2656 Q_ASSERT( curname );
2657 if ( ( curname[0] ==
'X' && curname[1] ==
'-' ) &&
2658 strcmp( curname, ICOrganizerProp ) != 0 ) {
2661 i->setNonKDECustomProperty(
2662 curname, QString::fromUtf8( s = fakeCString( vObjectUStringZValue( cur ) ) ) );
2668 void VCalFormat::writeCustomProperties( VObject *o,
const Incidence::Ptr &i )
2670 const QMap<QByteArray, QString> custom = i->customProperties();
2671 for ( QMap<QByteArray, QString>::ConstIterator c = custom.begin();
2672 c != custom.end(); ++c ) {
2673 if ( d->mManuallyWrittenExtensionFields.contains( c.key() ) ) {
2677 addPropValue( o, c.key(), c.value().toUtf8() );