40#include "versit/vcc.h"
41#include "versit/vobject.h"
45#include <klocalizedstring.h>
47#include <QtCore/QString>
48#include <QtCore/QRegExp>
49#include <QtCore/QFile>
50#include <QtCore/QByteArray>
51#include <QTextDocument>
60class KCal::VCalFormat::Private
69VCalFormat::VCalFormat() : d( new KCal::VCalFormat::Private )
73VCalFormat::~VCalFormat()
78bool 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 );
109bool 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 ) ) {
153bool VCalFormat::fromString(
Calendar *calendar,
const QString &
string )
155 return fromRawString( calendar,
string.toUtf8() );
158bool 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 );
195QString 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 );
229VObject *VCalFormat::eventToVTodo(
const Todo *anEvent )
234 vtodo = newVObject( VCTodoProp );
237 if ( anEvent->hasDueDate() ) {
238 tmpStr = kDateTimeToISO( anEvent->dtDue(), !anEvent->allDay() );
239 addPropValue( vtodo, VCDueProp, tmpStr.toLocal8Bit() );
243 if ( anEvent->hasStartDate() ) {
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() );
261 tmpStr = kDateTimeToISO( anEvent->lastModified() );
262 addPropValue( vtodo, VCLastModifiedProp, tmpStr.toLocal8Bit() );
266 if ( !anEvent->organizer().email().isEmpty() ) {
267 tmpStr =
"MAILTO:" + anEvent->organizer().email();
268 addPropValue( vtodo, ICOrganizerProp, tmpStr.toLocal8Bit() );
272 if ( anEvent->attendeeCount() > 0 ) {
273 Attendee::List::ConstIterator it;
275 for ( it = anEvent->attendees().begin(); it != anEvent->attendees().end();
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() ) );
295 if ( !anEvent->description().isEmpty() ) {
296 VObject *dObject = addPropValue( vtodo, VCDescriptionProp,
297 anEvent->description().toLocal8Bit() );
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" );
318 if ( anEvent->hasCompletedDate() ) {
319 tmpStr = kDateTimeToISO( anEvent->completed() );
320 addPropValue( vtodo, VCCompletedProp, tmpStr.toLocal8Bit() );
324 tmpStr.sprintf(
"%i", anEvent->priority() );
325 addPropValue( vtodo, VCPriorityProp, tmpStr.toLocal8Bit() );
328 if ( anEvent->relatedTo() ) {
329 addPropValue( vtodo, VCRelatedToProp,
330 anEvent->relatedTo()->uid().toLocal8Bit() );
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 ) {
359 if ( alarm->enabled() ) {
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() ) );
379 QString pilotId = anEvent->nonKDECustomProperty( KPilotIdProp );
380 if ( !pilotId.isEmpty() ) {
382 addPropValue( vtodo, KPilotIdProp, pilotId.toLocal8Bit() );
383 addPropValue( vtodo, KPilotStatusProp,
384 anEvent->nonKDECustomProperty( KPilotStatusProp ).toLocal8Bit() );
390VObject *VCalFormat::eventToVEvent(
const Event *anEvent )
395 vevent = newVObject( VCEventProp );
398 tmpStr = kDateTimeToISO( anEvent->dtStart(), !anEvent->allDay() );
399 addPropValue( vevent, VCDTstartProp, tmpStr.toLocal8Bit() );
403 if ( anEvent->dtStart() != anEvent->dtEnd() ) {
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() );
421 tmpStr = kDateTimeToISO( anEvent->lastModified() );
422 addPropValue( vevent, VCLastModifiedProp, tmpStr.toLocal8Bit() );
426 if ( !anEvent->organizer().email().isEmpty() ) {
427 tmpStr =
"MAILTO:" + anEvent->organizer().email();
428 addPropValue( vevent, ICOrganizerProp, tmpStr.toLocal8Bit() );
432 if ( anEvent->attendeeCount() > 0 ) {
433 Attendee::List::ConstIterator it;
434 for ( it = anEvent->attendees().constBegin(); it != anEvent->attendees().constEnd();
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() ) );
453 const Recurrence *recur = anEvent->recurrence();
454 if ( recur->recurs() ) {
455 bool validRecur =
true;
457 switch ( recur->recurrenceType() ) {
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!";
533 if ( recur->duration() > 0 ) {
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() );
564 if ( !anEvent->description().isEmpty() ) {
565 VObject *dObject = addPropValue( vevent, VCDescriptionProp,
566 anEvent->description().toLocal8Bit() );
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() );
634 tmpStrList = anEvent->resources();
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 ) {
644 if ( alarm->enabled() ) {
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() );
670 tmpStr.sprintf(
"%i", anEvent->transparency() );
671 addPropValue( vevent, VCTranspProp, tmpStr.toLocal8Bit() );
674 if ( anEvent->relatedTo() ) {
675 addPropValue( vevent, VCRelatedToProp, anEvent->relatedTo()->uid().toLocal8Bit() );
678 QString pilotId = anEvent->nonKDECustomProperty( KPilotIdProp );
679 if ( !pilotId.isEmpty() ) {
681 addPropValue( vevent, KPilotIdProp, pilotId.toLocal8Bit() );
682 addPropValue( vevent, KPilotStatusProp,
683 anEvent->nonKDECustomProperty( KPilotStatusProp ).toLocal8Bit() );
689Todo *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 ) ) ) );
717 anEvent->setLastModified( KDateTime::currentUtcDateTime() );
722 if ( ( vo = isAPropertyOf( vtodo, ICOrganizerProp ) ) != 0 ) {
723 anEvent->setOrganizer( s = fakeCString( vObjectUStringZValue( vo ) ) );
726 anEvent->setOrganizer( d->mCalendar->owner() );
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 ) ) );
766 anEvent->addAttendee( a );
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 ) {
796 anEvent->setCompleted(
true );
798 anEvent->setCompleted(
false );
802 anEvent->setCompleted(
false );
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 ) );
815 anEvent->setPriority( atoi( s ) );
821 if ( ( vo = isAPropertyOf( vtodo, VCDueProp ) ) != 0 ) {
822 anEvent->setDtDue( ISOToKDateTime( s = fakeCString( vObjectUStringZValue( vo ) ) ) );
824 anEvent->setHasDueDate(
true );
826 anEvent->setHasDueDate(
false );
830 if ( ( vo = isAPropertyOf( vtodo, VCDTstartProp ) ) != 0 ) {
831 anEvent->setDtStart( ISOToKDateTime( s = fakeCString( vObjectUStringZValue( vo ) ) ) );
833 anEvent->setHasStartDate(
true );
835 anEvent->setHasStartDate(
false );
839 if ( ( vo = isAPropertyOf( vtodo, VCDAlarmProp ) ) ) {
840 Alarm *alarm = anEvent->newAlarm();
842 if ( ( a = isAPropertyOf( vo, VCRunTimeProp ) ) ) {
843 alarm->
setTime( ISOToKDateTime( s = fakeCString( vObjectUStringZValue( a ) ) ) );
846 alarm->setEnabled(
true );
847 if ( ( vo = isAPropertyOf( vtodo, VCPAlarmProp ) ) ) {
848 if ( ( a = isAPropertyOf( vo, VCProcedureNameProp ) ) ) {
849 s = fakeCString( vObjectUStringZValue( a ) );
850 alarm->setProcedureAlarm( QFile::decodeName( s ) );
854 if ( ( vo = isAPropertyOf( vtodo, VCAAlarmProp ) ) ) {
855 if ( ( a = isAPropertyOf( vo, VCAudioContentProp ) ) ) {
856 s = fakeCString( vObjectUStringZValue( a ) );
857 alarm->setAudioAlarm( QFile::decodeName( s ) );
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(
';' );
876 anEvent->setCategories( tmpStrList );
880 if ( ( vo = isAPropertyOf( vtodo, KPilotIdProp ) ) ) {
881 anEvent->setNonKDECustomProperty(
882 KPilotIdProp, QString::fromLocal8Bit( s = fakeCString( vObjectUStringZValue( vo ) ) ) );
884 if ( ( vo = isAPropertyOf( vtodo, KPilotStatusProp ) ) ) {
885 anEvent->setNonKDECustomProperty(
886 KPilotStatusProp, QString::fromLocal8Bit( s = fakeCString( vObjectUStringZValue( vo ) ) ) );
889 anEvent->setNonKDECustomProperty( KPilotStatusProp, QString::number( SYNCMOD ) );
896Event *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 ) ) );
921 anEvent->setRevision( 0 );
922 if ( ( vo = isAPropertyOf( vevent, VCSequenceProp ) ) != 0 ) {
923 s = fakeCString( vObjectUStringZValue( vo ) );
925 anEvent->setRevision( atoi( s ) );
931 if ( ( vo = isAPropertyOf( vevent, VCLastModifiedProp ) ) != 0 ) {
932 anEvent->setLastModified( ISOToKDateTime( s = fakeCString( vObjectUStringZValue( vo ) ) ) );
935 anEvent->setLastModified( KDateTime::currentUtcDateTime() );
940 if ( ( vo = isAPropertyOf( vevent, ICOrganizerProp ) ) != 0 ) {
942 anEvent->setOrganizer( s = fakeCString( vObjectUStringZValue( vo ) ) );
945 anEvent->setOrganizer( d->mCalendar->owner() );
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 ) ) );
984 anEvent->addAttendee( a );
997 anEvent->setAllDay(
false );
1000 if ( ( vo = isAPropertyOf( vevent, VCDTstartProp ) ) != 0 ) {
1001 anEvent->setDtStart( ISOToKDateTime( s = fakeCString( vObjectUStringZValue( vo ) ) ) );
1003 if ( anEvent->dtStart().time().isNull() ) {
1004 anEvent->setAllDay(
true );
1009 if ( ( vo = isAPropertyOf( vevent, VCDTendProp ) ) != 0 ) {
1010 anEvent->setDtEnd( ISOToKDateTime( s = fakeCString( vObjectUStringZValue( vo ) ) ) );
1012 if ( anEvent->dtEnd().time().isNull() ) {
1013 anEvent->setAllDay(
true );
1019 if ( !( vo = isAPropertyOf( vevent, VCDTstartProp ) ) ) {
1020 anEvent->setDtStart( anEvent->dtEnd() );
1022 if ( !( vo = isAPropertyOf( vevent, VCDTendProp ) ) ) {
1023 anEvent->setDtEnd( anEvent->dtStart() );
1029 if ( ( vo = isAPropertyOf( vevent, VCRRuleProp ) ) != 0 ) {
1030 QString tmpStr = ( s = fakeCString( vObjectUStringZValue( vo ) ) );
1032 tmpStr = 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:
1066 anEvent->recurrence()->setDaily(rFreq);
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 );
1087 anEvent->recurrence()->setWeekly( rFreq, qba );
1091 case Recurrence::rMonthlyPos:
1093 anEvent->recurrence()->setMonthly( rFreq );
1097 if ( index == last ) {
1099 tmpPos = anEvent->dtStart().date().day() / 7 + 1;
1100 if ( tmpPos == 5 ) {
1103 qba.setBit( anEvent->dtStart().date().dayOfWeek() - 1 );
1104 anEvent->recurrence()->addMonthlyPos( tmpPos, qba );
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 );
1120 anEvent->recurrence()->addMonthlyPos( tmpPos, qba );
1128 case Recurrence::rMonthlyDay:
1129 anEvent->recurrence()->setMonthly( rFreq );
1130 if( index == last ) {
1132 short tmpDay = anEvent->dtStart().date().day();
1133 anEvent->recurrence()->addMonthlyDate( tmpDay );
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;
1144 anEvent->recurrence()->addMonthlyDate( tmpDay );
1149 case Recurrence::rYearlyMonth:
1150 anEvent->recurrence()->setYearly( rFreq );
1152 if ( index == last ) {
1154 short tmpMonth = anEvent->dtStart().date().month();
1155 anEvent->recurrence()->addYearlyMonth( tmpMonth );
1158 while ( index < last ) {
1159 int index2 = tmpStr.indexOf(
' ', index );
1160 short tmpMonth = tmpStr.mid( index, ( index2 - index ) ).toShort();
1162 anEvent->recurrence()->addYearlyMonth( tmpMonth );
1167 case Recurrence::rYearlyDay:
1168 anEvent->recurrence()->setYearly( rFreq );
1170 if ( index == last ) {
1172 short tmpDay = anEvent->dtStart().date().dayOfYear();
1173 anEvent->recurrence()->addYearlyDay( tmpDay );
1176 while ( index < last ) {
1177 int index2 = tmpStr.indexOf(
' ', index );
1178 short tmpDay = tmpStr.mid( index, ( index2 - index ) ).toShort();
1180 anEvent->recurrence()->addYearlyDay( tmpDay );
1191 if ( tmpStr.mid( index, 1 ) ==
"#" ) {
1194 int rDuration = tmpStr.mid( index, tmpStr.length() - index ).toInt();
1195 if ( rDuration > 0 ) {
1196 anEvent->recurrence()->setDuration( rDuration );
1198 }
else if ( tmpStr.indexOf(
'T', index ) != -1 ) {
1199 KDateTime rEndDate = ISOToKDateTime( tmpStr.mid( index, tmpStr.length() - index ) );
1200 rEndDate.setDateOnly(
true );
1201 anEvent->recurrence()->setEndDateTime( rEndDate );
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 );
1232 if ( !anEvent->description().isEmpty() ) {
1233 anEvent->setDescription(
1234 anEvent->description() +
'\n' + QString::fromLocal8Bit( s ), isRich );
1236 anEvent->setDescription( 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 ) );
1250 if ( anEvent->summary().isEmpty() && !( anEvent->description().isEmpty() ) ) {
1251 QString tmpStr = anEvent->description().simplified();
1252 anEvent->setDescription(
"" );
1253 anEvent->setSummary( tmpStr );
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 ) {
1279 anEvent->setSecrecy( secrecy );
1282 if ( ( vo = isAPropertyOf( vevent, VCCategoriesProp ) ) != 0 ) {
1283 s = fakeCString( vObjectUStringZValue( vo ) );
1284 QString categories = QString::fromLocal8Bit( s );
1286 QStringList tmpStrList = categories.split(
',' );
1287 anEvent->setCategories( tmpStrList );
1291 initPropIterator( &voi, vevent );
1292 while ( moreIteration( &voi ) ) {
1293 vo = nextVObject( &voi );
1294 if ( strcmp( vObjectName( vo ), VCAttachProp ) == 0 ) {
1295 s = fakeCString( vObjectUStringZValue( vo ) );
1296 anEvent->addAttachment(
new Attachment( QString( s ) ) );
1302 if ( ( vo = isAPropertyOf( vevent, VCResourcesProp ) ) != 0 ) {
1303 QString resources = ( s = fakeCString( vObjectUStringZValue( vo ) ) );
1305 QStringList tmpStrList = resources.split(
';' );
1306 anEvent->setResources( tmpStrList );
1310 if ( ( vo = isAPropertyOf( vevent, VCDAlarmProp ) ) ) {
1311 Alarm *alarm = anEvent->newAlarm();
1313 if ( ( a = isAPropertyOf( vo, VCRunTimeProp ) ) ) {
1314 alarm->
setTime( ISOToKDateTime( s = fakeCString( vObjectUStringZValue( a ) ) ) );
1317 alarm->setEnabled(
true );
1318 if ( ( vo = isAPropertyOf( vevent, VCPAlarmProp ) ) ) {
1319 if ( ( a = isAPropertyOf( vo, VCProcedureNameProp ) ) ) {
1320 s = fakeCString( vObjectUStringZValue( a ) );
1321 alarm->setProcedureAlarm( QFile::decodeName( s ) );
1325 if ( ( vo = isAPropertyOf( vevent, VCAAlarmProp ) ) ) {
1326 if ( ( a = isAPropertyOf( vo, VCAudioContentProp ) ) ) {
1327 s = fakeCString( vObjectUStringZValue( a ) );
1328 alarm->setAudioAlarm( QFile::decodeName( s ) );
1335 if ( ( vo = isAPropertyOf( vevent, VCPriorityProp ) ) ) {
1336 s = fakeCString( vObjectUStringZValue( vo ) );
1338 anEvent->setPriority( atoi( s ) );
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 ) ) ) {
1362 anEvent->setNonKDECustomProperty(
1363 KPilotIdProp, QString::fromLocal8Bit( s = fakeCString( vObjectUStringZValue( vo ) ) ) );
1365 if ( ( vo = isAPropertyOf( vevent, KPilotStatusProp ) ) ) {
1366 anEvent->setNonKDECustomProperty(
1367 KPilotStatusProp, QString::fromLocal8Bit( s = fakeCString( vObjectUStringZValue( vo ) ) ) );
1370 anEvent->setNonKDECustomProperty( KPilotStatusProp, QString::number( SYNCMOD ) );
1377QString VCalFormat::qDateToISO(
const QDate &qd )
1381 if ( !qd.isValid() ) {
1385 tmpStr.sprintf(
"%.2d%.2d%.2d", qd.year(), qd.month(), qd.day() );
1390QString 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() );
1414KDateTime 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() );
1443QDate 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 );
1457void 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...";
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() ) );
1597const char *VCalFormat::dayFromNum(
int day )
1599 const char *days[7] = {
"MO ",
"TU ",
"WE ",
"TH ",
"FR ",
"SA ",
"SU " };
1604int 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";
This file is part of the API for handling calendar data and defines the Calendar class.
Represents an alarm notification.
@ Audio
Play an audio file.
@ Procedure
Call a script.
void setTime(const KDateTime &alarmTime)
Sets the trigger time of the alarm.
Represents information related to an attachment for a Calendar Incidence.
ListBase< Attachment > List
List of attachments.
Represents information related to an attendee of an Calendar Incidence, typically a meeting or task (...
QString name() const
Returns the person name string.
PartStat
The different types of participant status.
@ Delegated
Event or to-do delegated.
@ Tentative
Event or to-do tentatively accepted.
@ Accepted
Event, to-do or journal accepted.
@ Completed
To-do completed.
@ NeedsAction
Event, to-do or journal needs action (default)
@ Declined
Event, to-do or journal declined.
@ InProcess
To-do in process of being completed.
Represents the main calendar class.
virtual bool addEvent(Event *event)=0
Inserts an Event into the calendar.
virtual Event::List events(EventSortField sortField=EventSortUnsorted, SortDirection sortDirection=SortDirectionAscending)
Returns a sorted, filtered list of all Events for this Calendar.
This class provides an Event in the sense of RFC2445.
@ Transparent
Event does not appear in free/busy time.
void setCreated(const KDateTime &dt)
Sets the incidence creation date/time.
Secrecy
The different types of incidence access classifications.
@ SecrecyPrivate
Secret to the owner.
@ SecrecyConfidential
Secret to the owner and some others.
@ SecrecyPublic
Not secret (default)
This class provides a template for lists of pointers.
This class represents a recurrence rule for a calendar incidence.
A QList which can be sorted.
Provides a To-do in the sense of RFC2445.