40 #include "versit/vcc.h"
41 #include "versit/vobject.h"
44 #include <kdatetime.h>
47 #include <QtCore/QString>
48 #include <QtCore/QRegExp>
49 #include <QtCore/QFile>
50 #include <QtCore/QByteArray>
51 #include <QTextDocument>
60 class KCal::VCalFormat::Private
69 VCalFormat::VCalFormat() : d( new KCal::VCalFormat::Private )
73 VCalFormat::~VCalFormat()
78 bool VCalFormat::load(
Calendar *calendar,
const QString &fileName )
80 d->mCalendar = calendar;
90 vcal = Parse_MIME_FromFileName( const_cast<char *>( QFile::encodeName( fileName ).data() ) );
103 cleanVObjects( vcal );
109 bool VCalFormat::save(
Calendar *calendar,
const QString &fileName )
111 d->mCalendar = calendar;
116 kDebug() << fileName;
118 vcal = newVObject( VCCalProp );
121 addPropValue( vcal, VCProdIdProp, productId().toLatin1() );
122 addPropValue( vcal, VCVersionProp, _VCAL_VERSION );
125 Todo::List todoList = d->mCalendar->rawTodos();
126 Todo::List::ConstIterator it;
127 for ( it = todoList.constBegin(); it != todoList.constEnd(); ++it ) {
128 vo = eventToVTodo( *it );
129 addVObjectProp( vcal, vo );
134 Event::List::ConstIterator it2;
135 for ( it2 = events.constBegin(); it2 != events.constEnd(); ++it2 ) {
136 vo = eventToVEvent( *it2 );
137 addVObjectProp( vcal, vo );
140 writeVObjectToFile( QFile::encodeName( fileName ).data(), vcal );
141 cleanVObjects( vcal );
144 if ( QFile::exists( fileName ) ) {
153 bool VCalFormat::fromString(
Calendar *calendar,
const QString &
string )
155 return fromRawString( calendar,
string.toUtf8() );
158 bool VCalFormat::fromRawString(
Calendar *calendar,
const QByteArray &
string )
160 d->mCalendar = calendar;
162 if ( !
string.size() ) {
166 VObject *vcal = Parse_MIME(
string.data(),
string.size() );
173 initPropIterator( &i, vcal );
177 curvo = nextVObject( &i );
178 }
while ( strcmp( vObjectName( curvo ), VCEventProp ) &&
179 strcmp( vObjectName( curvo ), VCTodoProp ) );
181 if ( strcmp( vObjectName( curvo ), VCEventProp ) == 0 ) {
182 Event *
event = VEventToEvent( curvo );
185 kDebug() <<
"Unknown object type.";
186 deleteVObject( vcal );
190 deleteVObject( vcal );
195 QString VCalFormat::toString(
Calendar *calendar )
198 d->mCalendar = calendar;
200 VObject *vcal = newVObject( VCCalProp );
203 addPropValue( vcal, VCVersionProp, _VCAL_VERSION );
207 if( events.isEmpty() ) {
208 cleanVObject ( vcal );
211 Event *
event = events.first();
213 cleanVObject ( vcal );
216 VObject *vevent = eventToVEvent( event );
218 addVObjectProp( vcal, vevent );
220 char *buf = writeMemVObject( 0, 0, vcal );
222 QString result( buf );
224 cleanVObject( vcal );
229 VObject *VCalFormat::eventToVTodo(
const Todo *anEvent )
234 vtodo = newVObject( VCTodoProp );
238 tmpStr = kDateTimeToISO( anEvent->
dtDue(), !anEvent->
allDay() );
239 addPropValue( vtodo, VCDueProp, tmpStr.toLocal8Bit() );
244 tmpStr = kDateTimeToISO( anEvent->
dtStart(), !anEvent->
allDay() );
245 addPropValue( vtodo, VCDTstartProp, tmpStr.toLocal8Bit() );
249 tmpStr = kDateTimeToISO( anEvent->
created() );
250 addPropValue( vtodo, VCDCreatedProp, tmpStr.toLocal8Bit() );
253 addPropValue( vtodo, VCUniqueStringProp,
254 anEvent->
uid().toLocal8Bit() );
257 tmpStr.sprintf(
"%i", anEvent->
revision() );
258 addPropValue( vtodo, VCSequenceProp, tmpStr.toLocal8Bit() );
262 addPropValue( vtodo, VCLastModifiedProp, tmpStr.toLocal8Bit() );
268 addPropValue( vtodo, ICOrganizerProp, tmpStr.toLocal8Bit() );
273 Attendee::List::ConstIterator it;
278 if ( !curAttendee->
email().isEmpty() &&
279 !curAttendee->
name().isEmpty() ) {
280 tmpStr =
"MAILTO:" + curAttendee->
name() +
" <" + curAttendee->
email() +
'>';
281 }
else if ( curAttendee->
name().isEmpty() ) {
282 tmpStr =
"MAILTO: " + curAttendee->
email();
283 }
else if ( curAttendee->
email().isEmpty() ) {
284 tmpStr =
"MAILTO: " + curAttendee->
name();
285 }
else if ( curAttendee->
name().isEmpty() && curAttendee->
email().isEmpty() ) {
286 kDebug() <<
"warning! this Event has an attendee w/o name or email!";
288 VObject *aProp = addPropValue( vtodo, VCAttendeeProp, tmpStr.toLocal8Bit() );
289 addPropValue( aProp, VCRSVPProp, curAttendee->
RSVP() ?
"TRUE" :
"FALSE" );
290 addPropValue( aProp, VCStatusProp, writeStatus( curAttendee->
status() ) );
296 VObject *dObject = addPropValue( vtodo, VCDescriptionProp,
298 if ( anEvent->
description().indexOf(
'\n' ) != -1 ) {
299 addPropValue( dObject, VCEncodingProp, VCQuotedPrintableProp );
304 if ( !anEvent->
summary().isEmpty() ) {
305 addPropValue( vtodo, VCSummaryProp, anEvent->
summary().toLocal8Bit() );
309 if ( !anEvent->
location().isEmpty() ) {
310 addPropValue( vtodo, VCLocationProp, anEvent->
location().toLocal8Bit() );
315 addPropValue( vtodo, VCStatusProp, anEvent->
isCompleted() ?
"COMPLETED" :
"NEEDS_ACTION" );
319 tmpStr = kDateTimeToISO( anEvent->
completed() );
320 addPropValue( vtodo, VCCompletedProp, tmpStr.toLocal8Bit() );
324 tmpStr.sprintf(
"%i", anEvent->
priority() );
325 addPropValue( vtodo, VCPriorityProp, tmpStr.toLocal8Bit() );
329 addPropValue( vtodo, VCRelatedToProp,
334 const QStringList tmpStrList = anEvent->
categories();
337 QStringList::const_iterator its;
338 for ( its = tmpStrList.constBegin(); its != tmpStrList.constEnd(); ++its ) {
340 if ( catStr[0] ==
' ' ) {
341 tmpStr += catStr.mid( 1 );
350 if ( !tmpStr.isEmpty() ) {
351 tmpStr.truncate( tmpStr.length() - 1 );
352 addPropValue( vtodo, VCCategoriesProp, tmpStr.toLocal8Bit() );
356 Alarm::List::ConstIterator it;
357 for ( it = anEvent->
alarms().begin(); it != anEvent->
alarms().end(); ++it ) {
360 VObject *a = addProp( vtodo, VCDAlarmProp );
361 tmpStr = kDateTimeToISO( alarm->
time() );
362 addPropValue( a, VCRunTimeProp, tmpStr.toLocal8Bit() );
363 addPropValue( a, VCRepeatCountProp,
"1" );
364 addPropValue( a, VCDisplayStringProp,
"beep!" );
366 a = addProp( vtodo, VCAAlarmProp );
367 addPropValue( a, VCRunTimeProp, tmpStr.toLocal8Bit() );
368 addPropValue( a, VCRepeatCountProp,
"1" );
369 addPropValue( a, VCAudioContentProp, QFile::encodeName( alarm->
audioFile() ) );
371 a = addProp( vtodo, VCPAlarmProp );
372 addPropValue( a, VCRunTimeProp, tmpStr.toLocal8Bit() );
373 addPropValue( a, VCRepeatCountProp,
"1" );
374 addPropValue( a, VCProcedureNameProp, QFile::encodeName( alarm->
programFile() ) );
380 if ( !pilotId.isEmpty() ) {
382 addPropValue( vtodo, KPilotIdProp, pilotId.toLocal8Bit() );
383 addPropValue( vtodo, KPilotStatusProp,
390 VObject *VCalFormat::eventToVEvent(
const Event *anEvent )
395 vevent = newVObject( VCEventProp );
398 tmpStr = kDateTimeToISO( anEvent->
dtStart(), !anEvent->
allDay() );
399 addPropValue( vevent, VCDTstartProp, tmpStr.toLocal8Bit() );
404 tmpStr = kDateTimeToISO( anEvent->
dtEnd(), !anEvent->
allDay() );
405 addPropValue( vevent, VCDTendProp, tmpStr.toLocal8Bit() );
409 tmpStr = kDateTimeToISO( anEvent->
created() );
410 addPropValue( vevent, VCDCreatedProp, tmpStr.toLocal8Bit() );
413 addPropValue( vevent, VCUniqueStringProp,
414 anEvent->
uid().toLocal8Bit() );
417 tmpStr.sprintf(
"%i", anEvent->
revision() );
418 addPropValue( vevent, VCSequenceProp, tmpStr.toLocal8Bit() );
422 addPropValue( vevent, VCLastModifiedProp, tmpStr.toLocal8Bit() );
428 addPropValue( vevent, ICOrganizerProp, tmpStr.toLocal8Bit() );
433 Attendee::List::ConstIterator it;
437 if ( !curAttendee->
email().isEmpty() && !curAttendee->
name().isEmpty() ) {
438 tmpStr =
"MAILTO:" + curAttendee->
name() +
" <" + curAttendee->
email() +
'>';
439 }
else if ( curAttendee->
name().isEmpty() ) {
440 tmpStr =
"MAILTO: " + curAttendee->
email();
441 }
else if ( curAttendee->
email().isEmpty() ) {
442 tmpStr =
"MAILTO: " + curAttendee->
name();
443 }
else if ( curAttendee->
name().isEmpty() && curAttendee->
email().isEmpty() ) {
444 kDebug() <<
"warning! this Event has an attendee w/o name or email!";
446 VObject *aProp = addPropValue( vevent, VCAttendeeProp, tmpStr.toLocal8Bit() );
447 addPropValue( aProp, VCRSVPProp, curAttendee->
RSVP() ?
"TRUE" :
"FALSE" );
448 addPropValue( aProp, VCStatusProp, writeStatus( curAttendee->
status() ) );
455 bool validRecur =
true;
458 case Recurrence::rDaily:
459 tmpStr.sprintf(
"D%i ", recur->
frequency() );
461 case Recurrence::rWeekly:
462 tmpStr.sprintf(
"W%i ", recur->
frequency() );
463 for (
int i = 0; i < 7; ++i ) {
464 QBitArray days ( recur->
days() );
465 if ( days.testBit(i) ) {
466 tmpStr += dayFromNum( i );
470 case Recurrence::rMonthlyPos:
472 tmpStr.sprintf(
"MP%i ", recur->
frequency() );
474 QList<RecurrenceRule::WDayPos> tmpPositions = recur->
monthPositions();
475 for ( QList<RecurrenceRule::WDayPos>::ConstIterator posit = tmpPositions.constBegin();
476 posit != tmpPositions.constEnd(); ++posit ) {
477 int pos = (*posit).pos();
478 tmpStr2.sprintf(
"%i", ( pos > 0 ) ? pos : (-pos) );
485 tmpStr += dayFromNum( (*posit).day() - 1 );
489 case Recurrence::rMonthlyDay:
491 tmpStr.sprintf(
"MD%i ", recur->
frequency() );
493 const QList<int> tmpDays = recur->
monthDays();
494 for ( QList<int>::ConstIterator tmpDay = tmpDays.constBegin();
495 tmpDay != tmpDays.constEnd(); ++tmpDay ) {
496 tmpStr2.sprintf(
"%i ", *tmpDay );
501 case Recurrence::rYearlyMonth:
503 tmpStr.sprintf(
"YM%i ", recur->
frequency() );
506 const QList<int> months = recur->
yearMonths();
507 for ( QList<int>::ConstIterator mit = months.constBegin();
508 mit != months.constEnd(); ++mit ) {
509 tmpStr2.sprintf(
"%i ", *mit );
514 case Recurrence::rYearlyDay:
516 tmpStr.sprintf(
"YD%i ", recur->
frequency() );
518 const QList<int> tmpDays = recur->
yearDays();
519 for ( QList<int>::ConstIterator tmpDay = tmpDays.begin();
520 tmpDay != tmpDays.end(); ++tmpDay ) {
521 tmpStr2.sprintf(
"%i ", *tmpDay );
528 kDebug() <<
"ERROR, it should never get here in eventToVEvent!";
534 tmpStr2.sprintf(
"#%i", recur->
duration() );
536 }
else if ( recur->
duration() == -1 ) {
539 tmpStr += kDateTimeToISO( recur->
endDateTime(), false );
544 addPropValue( vevent, VCRRuleProp, tmpStr.toLocal8Bit() );
550 DateList dateList = recur->exDates();
551 DateList::ConstIterator it;
554 for ( it = dateList.constBegin(); it != dateList.constEnd(); ++it ) {
555 tmpStr = qDateToISO(*it) +
';';
558 if ( !tmpStr2.isEmpty() ) {
559 tmpStr2.truncate( tmpStr2.length() - 1 );
560 addPropValue( vevent, VCExpDateProp, tmpStr2.toLocal8Bit() );
565 VObject *dObject = addPropValue( vevent, VCDescriptionProp,
567 if ( anEvent->
description().indexOf(
'\n' ) != -1 ) {
568 addPropValue( dObject, VCEncodingProp, VCQuotedPrintableProp );
573 if ( !anEvent->
summary().isEmpty() ) {
574 addPropValue( vevent, VCSummaryProp, anEvent->
summary().toLocal8Bit() );
578 if ( !anEvent->
location().isEmpty() ) {
579 addPropValue( vevent, VCLocationProp, anEvent->
location().toLocal8Bit() );
587 const char *text = 0;
588 switch ( anEvent->
secrecy() ) {
596 text =
"CONFIDENTIAL";
600 addPropValue( vevent, VCClassProp, text );
604 QStringList tmpStrList = anEvent->
categories();
607 for ( QStringList::const_iterator it = tmpStrList.constBegin(); it != tmpStrList.constEnd();
610 if ( catStr[0] ==
' ' ) {
611 tmpStr += catStr.mid( 1 );
620 if ( !tmpStr.isEmpty() ) {
621 tmpStr.truncate( tmpStr.length() - 1 );
622 addPropValue( vevent, VCCategoriesProp, tmpStr.toLocal8Bit() );
628 Attachment::List::ConstIterator atIt;
629 for ( atIt = attachments.constBegin(); atIt != attachments.constEnd(); ++atIt ) {
630 addPropValue( vevent, VCAttachProp, (*atIt)->uri().toLocal8Bit() );
635 tmpStr = tmpStrList.join(
";" );
636 if ( !tmpStr.isEmpty() ) {
637 addPropValue( vevent, VCResourcesProp, tmpStr.toLocal8Bit() );
641 Alarm::List::ConstIterator it2;
642 for ( it2 = anEvent->
alarms().constBegin(); it2 != anEvent->
alarms().constEnd(); ++it2 ) {
645 VObject *a = addProp( vevent, VCDAlarmProp );
646 tmpStr = kDateTimeToISO( alarm->
time() );
647 addPropValue( a, VCRunTimeProp, tmpStr.toLocal8Bit() );
648 addPropValue( a, VCRepeatCountProp,
"1" );
649 addPropValue( a, VCDisplayStringProp,
"beep!" );
651 a = addProp( vevent, VCAAlarmProp );
652 addPropValue( a, VCRunTimeProp, tmpStr.toLocal8Bit() );
653 addPropValue( a, VCRepeatCountProp,
"1" );
654 addPropValue( a, VCAudioContentProp, QFile::encodeName( alarm->
audioFile() ) );
657 a = addProp( vevent, VCPAlarmProp );
658 addPropValue( a, VCRunTimeProp, tmpStr.toLocal8Bit() );
659 addPropValue( a, VCRepeatCountProp,
"1" );
660 addPropValue( a, VCProcedureNameProp, QFile::encodeName( alarm->
programFile() ) );
666 tmpStr.sprintf(
"%i", anEvent->
priority() );
667 addPropValue( vevent, VCPriorityProp, tmpStr.toLocal8Bit() );
671 addPropValue( vevent, VCTranspProp, tmpStr.toLocal8Bit() );
675 addPropValue( vevent, VCRelatedToProp, anEvent->
relatedTo()->
uid().toLocal8Bit() );
679 if ( !pilotId.isEmpty() ) {
681 addPropValue( vevent, KPilotIdProp, pilotId.toLocal8Bit() );
682 addPropValue( vevent, KPilotStatusProp,
689 Todo *VCalFormat::VTodoToEvent( VObject *vtodo )
698 if ( ( vo = isAPropertyOf( vtodo, VCDCreatedProp ) ) != 0 ) {
699 anEvent->
setCreated( ISOToKDateTime( s = fakeCString( vObjectUStringZValue( vo ) ) ) );
704 vo = isAPropertyOf( vtodo, VCUniqueStringProp );
708 anEvent->
setUid( s = fakeCString( vObjectUStringZValue( vo ) ) );
713 if ( ( vo = isAPropertyOf( vtodo, VCLastModifiedProp ) ) != 0 ) {
714 anEvent->
setLastModified( ISOToKDateTime( s = fakeCString( vObjectUStringZValue( vo ) ) ) );
722 if ( ( vo = isAPropertyOf( vtodo, ICOrganizerProp ) ) != 0 ) {
723 anEvent->
setOrganizer( s = fakeCString( vObjectUStringZValue( vo ) ) );
730 initPropIterator( &voi, vtodo );
731 while ( moreIteration( &voi ) ) {
732 vo = nextVObject( &voi );
733 if ( strcmp( vObjectName( vo ), VCAttendeeProp ) == 0 ) {
736 s = fakeCString( vObjectUStringZValue( vo ) );
737 QString tmpStr = QString::fromLocal8Bit( s );
739 tmpStr = tmpStr.simplified();
740 int emailPos1, emailPos2;
741 if ( ( emailPos1 = tmpStr.indexOf(
'<' ) ) > 0 ) {
743 emailPos2 = tmpStr.lastIndexOf(
'>' );
744 a =
new Attendee( tmpStr.left( emailPos1 - 1 ),
745 tmpStr.mid( emailPos1 + 1,
746 emailPos2 - ( emailPos1 + 1 ) ) );
747 }
else if ( tmpStr.indexOf(
'@' ) > 0 ) {
753 QString email = tmpStr.replace(
' ',
'.' );
758 if ( ( vp = isAPropertyOf( vo, VCRSVPProp ) ) != 0 ) {
759 a->
setRSVP( vObjectStringZValue( vp ) );
762 if ( ( vp = isAPropertyOf( vo, VCStatusProp ) ) != 0 ) {
763 a->
setStatus( readStatus( vObjectStringZValue( vp ) ) );
771 if ( ( vo = isAPropertyOf( vtodo, VCDescriptionProp ) ) != 0 ) {
772 s = fakeCString( vObjectUStringZValue( vo ) );
773 anEvent->
setDescription( QString::fromLocal8Bit( s ), Qt::mightBeRichText( s ) );
778 if ( ( vo = isAPropertyOf( vtodo, VCSummaryProp ) ) ) {
779 s = fakeCString( vObjectUStringZValue( vo ) );
780 anEvent->
setSummary( QString::fromLocal8Bit( s ), Qt::mightBeRichText( s ) );
785 if ( ( vo = isAPropertyOf( vtodo, VCLocationProp ) ) != 0 ) {
786 s = fakeCString( vObjectUStringZValue( vo ) );
787 anEvent->
setLocation( QString::fromLocal8Bit( s ), Qt::mightBeRichText( s ) );
793 if ( ( vo = isAPropertyOf( vtodo, VCStatusProp ) ) != 0 ) {
794 s = fakeCString( vObjectUStringZValue( vo ) );
795 if ( s && strcmp( s,
"COMPLETED" ) == 0 ) {
806 if ( ( vo = isAPropertyOf( vtodo, VCCompletedProp ) ) != 0 ) {
807 anEvent->
setCompleted( ISOToKDateTime( s = fakeCString( vObjectUStringZValue( vo ) ) ) );
812 if ( ( vo = isAPropertyOf( vtodo, VCPriorityProp ) ) ) {
813 s = fakeCString( vObjectUStringZValue( vo ) );
821 if ( ( vo = isAPropertyOf( vtodo, VCDueProp ) ) != 0 ) {
822 anEvent->
setDtDue( ISOToKDateTime( s = fakeCString( vObjectUStringZValue( vo ) ) ) );
830 if ( ( vo = isAPropertyOf( vtodo, VCDTstartProp ) ) != 0 ) {
831 anEvent->
setDtStart( ISOToKDateTime( s = fakeCString( vObjectUStringZValue( vo ) ) ) );
839 if ( ( vo = isAPropertyOf( vtodo, VCDAlarmProp ) ) ) {
842 if ( ( a = isAPropertyOf( vo, VCRunTimeProp ) ) ) {
843 alarm->
setTime( ISOToKDateTime( s = fakeCString( vObjectUStringZValue( a ) ) ) );
847 if ( ( vo = isAPropertyOf( vtodo, VCPAlarmProp ) ) ) {
848 if ( ( a = isAPropertyOf( vo, VCProcedureNameProp ) ) ) {
849 s = fakeCString( vObjectUStringZValue( a ) );
854 if ( ( vo = isAPropertyOf( vtodo, VCAAlarmProp ) ) ) {
855 if ( ( a = isAPropertyOf( vo, VCAudioContentProp ) ) ) {
856 s = fakeCString( vObjectUStringZValue( a ) );
864 if ( ( vo = isAPropertyOf( vtodo, VCRelatedToProp ) ) != 0 ) {
865 anEvent->
setRelatedToUid( s = fakeCString( vObjectUStringZValue( vo ) ) );
867 d->mTodosRelate.append( anEvent );
871 if ( ( vo = isAPropertyOf( vtodo, VCCategoriesProp ) ) != 0 ) {
872 s = fakeCString( vObjectUStringZValue( vo ) );
873 QString categories = QString::fromLocal8Bit( s );
875 QStringList tmpStrList = categories.split(
';' );
880 if ( ( vo = isAPropertyOf( vtodo, KPilotIdProp ) ) ) {
882 KPilotIdProp, QString::fromLocal8Bit( s = fakeCString( vObjectUStringZValue( vo ) ) ) );
884 if ( ( vo = isAPropertyOf( vtodo, KPilotStatusProp ) ) ) {
886 KPilotStatusProp, QString::fromLocal8Bit( s = fakeCString( vObjectUStringZValue( vo ) ) ) );
896 Event *VCalFormat::VEventToEvent( VObject *vevent )
905 if ( ( vo = isAPropertyOf( vevent, VCDCreatedProp ) ) != 0 ) {
906 anEvent->
setCreated( ISOToKDateTime( s = fakeCString( vObjectUStringZValue( vo ) ) ) );
911 vo = isAPropertyOf( vevent, VCUniqueStringProp );
915 anEvent->
setUid( s = fakeCString( vObjectUStringZValue( vo ) ) );
922 if ( ( vo = isAPropertyOf( vevent, VCSequenceProp ) ) != 0 ) {
923 s = fakeCString( vObjectUStringZValue( vo ) );
931 if ( ( vo = isAPropertyOf( vevent, VCLastModifiedProp ) ) != 0 ) {
932 anEvent->
setLastModified( ISOToKDateTime( s = fakeCString( vObjectUStringZValue( vo ) ) ) );
940 if ( ( vo = isAPropertyOf( vevent, ICOrganizerProp ) ) != 0 ) {
942 anEvent->
setOrganizer( s = fakeCString( vObjectUStringZValue( vo ) ) );
949 initPropIterator( &voi, vevent );
950 while ( moreIteration( &voi ) ) {
951 vo = nextVObject( &voi );
952 if ( strcmp( vObjectName( vo ), VCAttendeeProp ) == 0 ) {
955 s = fakeCString( vObjectUStringZValue( vo ) );
956 QString tmpStr = QString::fromLocal8Bit( s );
958 tmpStr = tmpStr.simplified();
959 int emailPos1, emailPos2;
960 if ( ( emailPos1 = tmpStr.indexOf(
'<' ) ) > 0 ) {
962 emailPos2 = tmpStr.lastIndexOf(
'>' );
963 a =
new Attendee( tmpStr.left( emailPos1 - 1 ),
964 tmpStr.mid( emailPos1 + 1,
965 emailPos2 - ( emailPos1 + 1 ) ) );
966 }
else if ( tmpStr.indexOf(
'@' ) > 0 ) {
971 QString email = tmpStr.replace(
' ',
'.' );
976 if ( ( vp = isAPropertyOf( vo, VCRSVPProp ) ) != 0 ) {
977 a->
setRSVP( vObjectStringZValue( vp ) );
980 if ( ( vp = isAPropertyOf( vo, VCStatusProp ) ) != 0 ) {
981 a->
setStatus( readStatus( vObjectStringZValue( vp ) ) );
1000 if ( ( vo = isAPropertyOf( vevent, VCDTstartProp ) ) != 0 ) {
1001 anEvent->
setDtStart( ISOToKDateTime( s = fakeCString( vObjectUStringZValue( vo ) ) ) );
1003 if ( anEvent->
dtStart().time().isNull() ) {
1009 if ( ( vo = isAPropertyOf( vevent, VCDTendProp ) ) != 0 ) {
1010 anEvent->
setDtEnd( ISOToKDateTime( s = fakeCString( vObjectUStringZValue( vo ) ) ) );
1012 if ( anEvent->
dtEnd().time().isNull() ) {
1019 if ( !( vo = isAPropertyOf( vevent, VCDTstartProp ) ) ) {
1022 if ( !( vo = isAPropertyOf( vevent, VCDTendProp ) ) ) {
1029 if ( ( vo = isAPropertyOf( vevent, VCRRuleProp ) ) != 0 ) {
1030 QString tmpStr = ( s = fakeCString( vObjectUStringZValue( vo ) ) );
1032 tmpStr.simplified();
1033 tmpStr = tmpStr.toUpper();
1037 uint type = Recurrence::rNone;
1038 if ( tmpStr.left(1) ==
"D" ) {
1039 type = Recurrence::rDaily;
1040 }
else if ( tmpStr.left(1) ==
"W" ) {
1041 type = Recurrence::rWeekly;
1044 if ( tmpStr.left(2) ==
"MP" ) {
1045 type = Recurrence::rMonthlyPos;
1046 }
else if ( tmpStr.left(2) ==
"MD" ) {
1047 type = Recurrence::rMonthlyDay;
1048 }
else if ( tmpStr.left(2) ==
"YM" ) {
1049 type = Recurrence::rYearlyMonth;
1050 }
else if ( tmpStr.left(2) ==
"YD" ) {
1051 type = Recurrence::rYearlyDay;
1055 if ( type != Recurrence::rNone ) {
1058 int index = tmpStr.indexOf(
' ' );
1059 int last = tmpStr.lastIndexOf(
' ' ) + 1;
1060 int rFreq = tmpStr.mid( typelen, ( index - 1 ) ).toInt();
1065 case Recurrence::rDaily:
1069 case Recurrence::rWeekly:
1073 if ( index == last ) {
1075 qba.setBit( anEvent->
dtStart().date().dayOfWeek() - 1 );
1078 while ( index < last ) {
1079 dayStr = tmpStr.mid( index, 3 );
1080 int dayNum = numFromDay( dayStr );
1081 if ( dayNum >= 0 ) {
1082 qba.setBit( dayNum );
1091 case Recurrence::rMonthlyPos:
1097 if ( index == last ) {
1099 tmpPos = anEvent->
dtStart().date().day() / 7 + 1;
1100 if ( tmpPos == 5 ) {
1103 qba.setBit( anEvent->
dtStart().date().dayOfWeek() - 1 );
1107 while ( index < last ) {
1108 tmpPos = tmpStr.mid( index, 1 ).toShort();
1110 if ( tmpStr.mid( index, 1 ) ==
"-" ) {
1112 tmpPos = 0 - tmpPos;
1115 while ( numFromDay( tmpStr.mid( index, 3 ) ) >= 0 ) {
1116 int dayNum = numFromDay( tmpStr.mid( index, 3 ) );
1117 qba.setBit( dayNum );
1128 case Recurrence::rMonthlyDay:
1130 if( index == last ) {
1132 short tmpDay = anEvent->
dtStart().date().day();
1136 while ( index < last ) {
1137 int index2 = tmpStr.indexOf(
' ', index );
1138 short tmpDay = tmpStr.mid( index, ( index2 - index ) ).toShort();
1140 if ( tmpStr.mid( index, 1 ) ==
"-" ) {
1141 tmpDay = 0 - tmpDay;
1149 case Recurrence::rYearlyMonth:
1152 if ( index == last ) {
1154 short tmpMonth = anEvent->
dtStart().date().month();
1158 while ( index < last ) {
1159 int index2 = tmpStr.indexOf(
' ', index );
1160 short tmpMonth = tmpStr.mid( index, ( index2 - index ) ).toShort();
1167 case Recurrence::rYearlyDay:
1170 if ( index == last ) {
1172 short tmpDay = anEvent->
dtStart().date().dayOfYear();
1176 while ( index < last ) {
1177 int index2 = tmpStr.indexOf(
' ', index );
1178 short tmpDay = tmpStr.mid( index, ( index2 - index ) ).toShort();
1191 if ( tmpStr.mid( index, 1 ) ==
"#" ) {
1194 int rDuration = tmpStr.mid( index, tmpStr.length() - index ).toInt();
1195 if ( rDuration > 0 ) {
1198 }
else if ( tmpStr.indexOf(
'T', index ) != -1 ) {
1199 KDateTime rEndDate = ISOToKDateTime( tmpStr.mid( index, tmpStr.length() - index ) );
1200 rEndDate.setDateOnly(
true );
1206 kDebug() <<
"we don't understand this type of recurrence!";
1211 if ( ( vo = isAPropertyOf( vevent, VCExpDateProp ) ) != 0 ) {
1212 s = fakeCString( vObjectUStringZValue( vo ) );
1213 QStringList exDates = QString::fromLocal8Bit( s ).split(
',' );
1214 QStringList::ConstIterator it;
1215 for ( it = exDates.constBegin(); it != exDates.constEnd(); ++it ) {
1216 anEvent->
recurrence()->addExDate( ISOToQDate(*it) );
1222 if ( ( vo = isAPropertyOf( vevent, VCSummaryProp ) ) ) {
1223 s = fakeCString( vObjectUStringZValue( vo ) );
1224 anEvent->
setSummary( QString::fromLocal8Bit( s ), Qt::mightBeRichText( s ) );
1229 if ( ( vo = isAPropertyOf( vevent, VCDescriptionProp ) ) != 0 ) {
1230 s = fakeCString( vObjectUStringZValue( vo ) );
1231 bool isRich = Qt::mightBeRichText( s );
1234 anEvent->
description() +
'\n' + QString::fromLocal8Bit( s ), isRich );
1242 if ( ( vo = isAPropertyOf( vevent, VCLocationProp ) ) != 0 ) {
1243 s = fakeCString( vObjectUStringZValue( vo ) );
1244 anEvent->
setLocation( QString::fromLocal8Bit( s ), Qt::mightBeRichText( s ) );
1251 QString tmpStr = anEvent->
description().simplified();
1258 if ( ( vo = isAPropertyOf( vevent, VCStatusProp ) ) != 0 ) {
1259 QString tmpStr( s = fakeCString( vObjectUStringZValue( vo ) ) );
1270 if ( ( vo = isAPropertyOf( vevent, VCClassProp ) ) != 0 ) {
1271 s = fakeCString( vObjectUStringZValue( vo ) );
1272 if ( s && strcmp( s,
"PRIVATE" ) == 0 ) {
1274 }
else if ( s && strcmp( s,
"CONFIDENTIAL" ) == 0 ) {
1282 if ( ( vo = isAPropertyOf( vevent, VCCategoriesProp ) ) != 0 ) {
1283 s = fakeCString( vObjectUStringZValue( vo ) );
1284 QString categories = QString::fromLocal8Bit( s );
1286 QStringList tmpStrList = categories.split(
',' );
1291 initPropIterator( &voi, vevent );
1292 while ( moreIteration( &voi ) ) {
1293 vo = nextVObject( &voi );
1294 if ( strcmp( vObjectName( vo ), VCAttachProp ) == 0 ) {
1295 s = fakeCString( vObjectUStringZValue( vo ) );
1302 if ( ( vo = isAPropertyOf( vevent, VCResourcesProp ) ) != 0 ) {
1303 QString resources = ( s = fakeCString( vObjectUStringZValue( vo ) ) );
1305 QStringList tmpStrList = resources.split(
';' );
1310 if ( ( vo = isAPropertyOf( vevent, VCDAlarmProp ) ) ) {
1313 if ( ( a = isAPropertyOf( vo, VCRunTimeProp ) ) ) {
1314 alarm->
setTime( ISOToKDateTime( s = fakeCString( vObjectUStringZValue( a ) ) ) );
1318 if ( ( vo = isAPropertyOf( vevent, VCPAlarmProp ) ) ) {
1319 if ( ( a = isAPropertyOf( vo, VCProcedureNameProp ) ) ) {
1320 s = fakeCString( vObjectUStringZValue( a ) );
1325 if ( ( vo = isAPropertyOf( vevent, VCAAlarmProp ) ) ) {
1326 if ( ( a = isAPropertyOf( vo, VCAudioContentProp ) ) ) {
1327 s = fakeCString( vObjectUStringZValue( a ) );
1335 if ( ( vo = isAPropertyOf( vevent, VCPriorityProp ) ) ) {
1336 s = fakeCString( vObjectUStringZValue( vo ) );
1344 if ( ( vo = isAPropertyOf( vevent, VCTranspProp ) ) != 0 ) {
1345 s = fakeCString( vObjectUStringZValue( vo ) );
1354 if ( ( vo = isAPropertyOf( vevent, VCRelatedToProp ) ) != 0 ) {
1355 anEvent->
setRelatedToUid( s = fakeCString( vObjectUStringZValue( vo ) ) );
1357 d->mEventsRelate.append( anEvent );
1361 if ( ( vo = isAPropertyOf( vevent, KPilotIdProp ) ) ) {
1363 KPilotIdProp, QString::fromLocal8Bit( s = fakeCString( vObjectUStringZValue( vo ) ) ) );
1365 if ( ( vo = isAPropertyOf( vevent, KPilotStatusProp ) ) ) {
1367 KPilotStatusProp, QString::fromLocal8Bit( s = fakeCString( vObjectUStringZValue( vo ) ) ) );
1377 QString VCalFormat::qDateToISO(
const QDate &qd )
1381 if ( !qd.isValid() ) {
1385 tmpStr.sprintf(
"%.2d%.2d%.2d", qd.year(), qd.month(), qd.day() );
1390 QString VCalFormat::kDateTimeToISO(
const KDateTime &dt,
bool zulu )
1394 if ( !dt.isValid() ) {
1400 tmpDT = dt.toUtc().dateTime();
1402 tmpDT = dt.toTimeSpec( d->mCalendar->timeSpec() ).dateTime();
1404 tmpStr.sprintf(
"%.2d%.2d%.2dT%.2d%.2d%.2d",
1405 tmpDT.date().year(), tmpDT.date().month(),
1406 tmpDT.date().day(), tmpDT.time().hour(),
1407 tmpDT.time().minute(), tmpDT.time().second() );
1414 KDateTime VCalFormat::ISOToKDateTime(
const QString &dtStr )
1419 int year, month, day, hour, minute, second;
1422 year = tmpStr.left( 4 ).toInt();
1423 month = tmpStr.mid( 4, 2 ).toInt();
1424 day = tmpStr.mid( 6, 2 ).toInt();
1425 hour = tmpStr.mid( 9, 2 ).toInt();
1426 minute = tmpStr.mid( 11, 2 ).toInt();
1427 second = tmpStr.mid( 13, 2 ).toInt();
1428 tmpDate.setYMD( year, month, day );
1429 tmpTime.setHMS( hour, minute, second );
1431 if ( tmpDate.isValid() && tmpTime.isValid() ) {
1433 if ( dtStr.at( dtStr.length() - 1 ) ==
'Z' ) {
1434 return KDateTime( tmpDate, tmpTime, KDateTime::UTC );
1436 return KDateTime( tmpDate, tmpTime, d->mCalendar->timeSpec() );
1443 QDate VCalFormat::ISOToQDate(
const QString &dateStr )
1445 int year, month, day;
1447 year = dateStr.left( 4 ).toInt();
1448 month = dateStr.mid( 4, 2 ).toInt();
1449 day = dateStr.mid( 6, 2 ).toInt();
1451 return QDate( year, month, day );
1457 void VCalFormat::populate( VObject *vcal )
1463 VObject *curVO, *curVOProp;
1466 if ( ( curVO = isAPropertyOf( vcal, ICMethodProp ) ) != 0 ) {
1467 char *methodType = 0;
1468 methodType = fakeCString( vObjectUStringZValue( curVO ) );
1469 kDebug() <<
"This calendar is an iTIP transaction of type '"
1470 << methodType <<
"'";
1471 deleteStr( methodType );
1475 if ( ( curVO = isAPropertyOf( vcal, VCProdIdProp ) ) != 0 ) {
1476 char *s = fakeCString( vObjectUStringZValue( curVO ) );
1477 if ( !s || strcmp( productId().toLocal8Bit(), s ) != 0 ) {
1478 kDebug() <<
"This vCalendar file was not created by KOrganizer or"
1479 <<
"any other product we support. Loading anyway...";
1481 setLoadedProductId( s );
1486 if ( ( curVO = isAPropertyOf( vcal, VCVersionProp ) ) != 0 ) {
1487 char *s = fakeCString( vObjectUStringZValue( curVO ) );
1488 if ( !s || strcmp( _VCAL_VERSION, s ) != 0 ) {
1489 kDebug() <<
"This vCalendar file has version" << s
1490 <<
"We only support" << _VCAL_VERSION;
1497 if ( ( curVO = isAPropertyOf( vcal, VCTimeZoneProp ) ) != 0 ) {
1498 char *s = fakeCString( vObjectUStringZValue( curVO ) );
1499 d->mCalendar->setTimeZone( s );
1505 d->mEventsRelate.clear();
1506 d->mTodosRelate.clear();
1508 initPropIterator( &i, vcal );
1511 while ( moreIteration( &i ) ) {
1512 curVO = nextVObject( &i );
1517 if ( strcmp( vObjectName( curVO ), VCEventProp ) == 0 ) {
1519 if ( ( curVOProp = isAPropertyOf( curVO, KPilotStatusProp ) ) != 0 ) {
1521 s = fakeCString( vObjectUStringZValue( curVOProp ) );
1524 if ( atoi( s ) == SYNCDEL ) {
1526 kDebug() <<
"skipping pilot-deleted event";
1536 if ( ( curVOProp = isAPropertyOf( curVO, VCUniqueStringProp ) ) != 0 ) {
1537 char *s = fakeCString( vObjectUStringZValue( curVOProp ) );
1538 QString tmpStr( s );
1541 if ( d->mCalendar->incidence( tmpStr ) ) {
1546 if ( ( !( curVOProp = isAPropertyOf( curVO, VCDTstartProp ) ) ) &&
1547 ( !( curVOProp = isAPropertyOf( curVO, VCDTendProp ) ) ) ) {
1548 kDebug() <<
"found a VEvent with no DTSTART and no DTEND! Skipping...";
1552 anEvent = VEventToEvent( curVO );
1556 if ( anEvent->
dtStart().isValid() && anEvent->
dtEnd().isValid() ) {
1557 d->mCalendar->addEvent( anEvent );
1563 }
else if ( strcmp( vObjectName( curVO ), VCTodoProp ) == 0 ) {
1564 Todo *aTodo = VTodoToEvent( curVO );
1566 Todo *old = d->mCalendar->todo( aTodo->
uid() );
1568 d->mCalendar->deleteTodo( old );
1569 d->mTodosRelate.removeAll( old );
1572 d->mCalendar->addTodo( aTodo );
1573 }
else if ( ( strcmp( vObjectName( curVO ), VCVersionProp ) == 0 ) ||
1574 ( strcmp( vObjectName( curVO ), VCProdIdProp ) == 0 ) ||
1575 ( strcmp( vObjectName( curVO ), VCTimeZoneProp ) == 0 ) ) {
1580 kDebug() <<
"Ignoring unknown vObject \"" << vObjectName(curVO) <<
"\"";
1587 Event::List::ConstIterator eIt;
1588 for ( eIt = d->mEventsRelate.constBegin(); eIt != d->mEventsRelate.constEnd(); ++eIt ) {
1589 (*eIt)->setRelatedTo( d->mCalendar->incidence( (*eIt)->relatedToUid() ) );
1591 Todo::List::ConstIterator tIt;
1592 for ( tIt = d->mTodosRelate.constBegin(); tIt != d->mTodosRelate.constEnd(); ++tIt ) {
1593 (*tIt)->setRelatedTo( d->mCalendar->incidence( (*tIt)->relatedToUid() ) );
1597 const char *VCalFormat::dayFromNum(
int day )
1599 const char *days[7] = {
"MO ",
"TU ",
"WE ",
"TH ",
"FR ",
"SA ",
"SU " };
1604 int VCalFormat::numFromDay(
const QString &day )
1606 if ( day ==
"MO " ) {
1609 if ( day ==
"TU " ) {
1612 if ( day ==
"WE " ) {
1615 if ( day ==
"TH " ) {
1618 if ( day ==
"FR " ) {
1621 if ( day ==
"SA " ) {
1624 if ( day ==
"SU " ) {
1633 QString statStr = s;
1634 statStr = statStr.toUpper();
1637 if ( statStr ==
"X-ACTION" ) {
1639 }
else if ( statStr ==
"NEEDS ACTION" ) {
1641 }
else if ( statStr ==
"ACCEPTED" ) {
1643 }
else if ( statStr ==
"SENT" ) {
1645 }
else if ( statStr ==
"TENTATIVE" ) {
1647 }
else if ( statStr ==
"CONFIRMED" ) {
1649 }
else if ( statStr ==
"DECLINED" ) {
1651 }
else if ( statStr ==
"COMPLETED" ) {
1653 }
else if ( statStr ==
"DELEGATED" ) {
1656 kDebug() <<
"error setting attendee mStatus, unknown mStatus!";
1668 return "NEEDS ACTION";
1686 return "NEEDS ACTION";