39 #include <KTemporaryFile>
41 #include <QTextDocument>
43 using namespace KCalCore;
50 class KCalCore::Incidence::Private
55 mDescriptionIsRich( false ),
56 mSummaryIsRich( false ),
57 mLocationIsRich( false ),
59 mStatus( StatusNone ),
60 mSecrecy( SecrecyPublic ),
62 mGeoLatitude( INVALID_LATLON ),
63 mGeoLongitude( INVALID_LATLON ),
69 Private(
const Private &p )
70 : mCreated( p.mCreated ),
71 mRevision( p.mRevision ),
72 mDescription( p.mDescription ),
73 mDescriptionIsRich( p.mDescriptionIsRich ),
74 mSummary( p.mSummary ),
75 mSummaryIsRich( p.mSummaryIsRich ),
76 mLocation( p.mLocation ),
77 mLocationIsRich( p.mLocationIsRich ),
78 mCategories( p.mCategories ),
80 mResources( p.mResources ),
82 mStatusString( p.mStatusString ),
83 mSecrecy( p.mSecrecy ),
84 mPriority( p.mPriority ),
85 mSchedulingID( p.mSchedulingID ),
86 mRelatedToUid( p.mRelatedToUid ),
87 mGeoLatitude( p.mGeoLatitude ),
88 mGeoLongitude( p.mGeoLongitude ),
90 mRecurrenceId( p.mRecurrenceId ),
105 mRevision = src.d->mRevision;
106 mCreated = src.d->mCreated;
107 mDescription = src.d->mDescription;
108 mSummary = src.d->mSummary;
109 mCategories = src.d->mCategories;
110 mRelatedToUid = src.d->mRelatedToUid;
111 mResources = src.d->mResources;
112 mStatusString = src.d->mStatusString;
113 mStatus = src.d->mStatus;
114 mSecrecy = src.d->mSecrecy;
115 mPriority = src.d->mPriority;
116 mLocation = src.d->mLocation;
117 mGeoLatitude = src.d->mGeoLatitude;
118 mGeoLongitude = src.d->mGeoLongitude;
119 mHasGeo = src.d->mHasGeo;
120 mRecurrenceId = src.d->mRecurrenceId;
121 mLocalOnly = src.d->mLocalOnly;
126 foreach (
Alarm::Ptr alarm, src.d->mAlarms ) {
128 b->setParent( dest );
134 mAttachments.append( a );
137 if ( src.d->mRecurrence ) {
138 mRecurrence =
new Recurrence( *( src.d->mRecurrence ) );
139 mRecurrence->addObserver( dest );
148 QString mDescription;
149 bool mDescriptionIsRich;
153 bool mLocationIsRich;
154 QStringList mCategories;
158 QStringList mResources;
160 QString mStatusString;
163 QString mSchedulingID;
165 QMap<RelType,QString> mRelatedToUid;
169 QHash<Attachment::Ptr,QString> mTempFiles;
170 KDateTime mRecurrenceId;
185 d( new KCalCore::
Incidence::Private( *i.d ) )
196 alarm->setParent( 0 );
199 delete d->mRecurrence;
205 static bool stringCompare(
const QString &s1,
const QString &s2 )
207 return ( s1.isEmpty() && s2.isEmpty() ) || ( s1 == s2 );
213 if ( &other !=
this ) {
237 Alarm::List::ConstIterator a1 =
alarms().constBegin();
238 Alarm::List::ConstIterator a1end =
alarms().constEnd();
239 Alarm::List::ConstIterator a2 = i2->
alarms().constBegin();
240 Alarm::List::ConstIterator a2end = i2->
alarms().constEnd();
241 for ( ; a1 != a1end && a2 != a2end; ++a1, ++a2 ) {
242 if ( **a1 == **a2 ) {
253 Attachment::List::ConstIterator att1 =
attachments().constBegin();
254 const Attachment::List::ConstIterator att1end =
attachments().constEnd();
255 Attachment::List::ConstIterator att2 = i2->
attachments().constBegin();
256 const Attachment::List::ConstIterator att2end = i2->
attachments().constEnd();
257 for ( ; att1 != att1end && att2 != att2end; ++att1, ++att2 ) {
258 if ( **att1 == **att2 ) {
265 bool recurrenceEqual = ( d->mRecurrence == 0 && i2->d->mRecurrence == 0 );
266 if ( !recurrenceEqual ) {
269 recurrenceEqual = d->mRecurrence != 0 &&
270 i2->d->mRecurrence != 0 &&
271 *d->mRecurrence == *i2->d->mRecurrence;
282 d->mStatus == i2->d->mStatus &&
284 stringCompare( d->mStatusString, i2->d->mStatusString ) ) &&
293 const KDateTime nowUTC = KDateTime::currentUtcDateTime();
303 if ( !d->mLocalOnly ) {
311 if ( d->mRecurrence ) {
312 d->mRecurrence->setRecurReadOnly( readOnly );
326 return d->mLocalOnly;
334 if ( d->mRecurrence ) {
335 d->mRecurrence->setAllDay( allDay );
346 d->mCreated = created.toUtc();
378 if ( d->mRecurrence ) {
379 d->mRecurrence->setStartDateTime( dt );
380 d->mRecurrence->setAllDay(
allDay() );
386 const KDateTime::Spec &newSpec )
389 if ( d->mRecurrence ) {
390 d->mRecurrence->shiftTimes( oldSpec, newSpec );
392 for (
int i = 0, end = d->mAlarms.count(); i < end; ++i ) {
393 d->mAlarms[i]->shiftTimes( oldSpec, newSpec );
404 d->mDescriptionIsRich = isRich;
411 setDescription( description, Qt::mightBeRichText( description ) );
416 return d->mDescription;
422 return d->mDescription;
424 return Qt::escape( d->mDescription ).replace(
'\n',
"<br/>" );
430 return d->mDescriptionIsRich;
440 d->mSummaryIsRich = isRich;
447 setSummary( summary, Qt::mightBeRichText( summary ) );
460 return Qt::escape( d->mSummary ).replace(
'\n',
"<br/>" );
466 return d->mSummaryIsRich;
488 d->mCategories.clear();
490 if ( catStr.isEmpty() ) {
495 d->mCategories = catStr.split(
',' );
497 QStringList::Iterator it;
498 for ( it = d->mCategories.begin();it != d->mCategories.end(); ++it ) {
499 *it = ( *it ).trimmed();
507 return d->mCategories;
512 return d->mCategories.join(
"," );
520 if ( d->mRelatedToUid[relType] != relatedToUid ) {
522 d->mRelatedToUid[relType] = relatedToUid;
530 return d->mRelatedToUid.value( relType );
537 if ( !d->mRecurrence ) {
540 d->mRecurrence->setAllDay(
allDay() );
541 d->mRecurrence->setRecurReadOnly(
mReadOnly );
542 d->mRecurrence->addObserver( const_cast<KCalCore::Incidence*>(
this ) );
545 return d->mRecurrence;
550 delete d->mRecurrence;
556 if ( d->mRecurrence ) {
557 return d->mRecurrence->recurrenceType();
559 return Recurrence::rNone;
565 if ( d->mRecurrence ) {
566 return d->mRecurrence->recurs();
573 const KDateTime::Spec &timeSpec )
const
575 return d->mRecurrence && d->mRecurrence->recursOn( date, timeSpec );
580 return d->mRecurrence && d->mRecurrence->recursAt( qdt );
584 const KDateTime::Spec &timeSpec )
const
587 KDateTime end =
dateTime( RoleEndRecurrenceBase );
589 QList<KDateTime> result;
592 if ( !start.isValid() && ! end.isValid() ) {
597 KDateTime kdate( date, timeSpec );
599 if ( !( start > kdate || end < kdate ) ) {
605 int days = start.daysTo( end );
607 QDate tmpday( date.addDays( -days - 1 ) );
609 while ( tmpday <= date ) {
612 foreach (
const QTime &time, times ) {
613 tmp = KDateTime( tmpday, time, start.timeSpec() );
619 tmpday = tmpday.addDays( 1 );
627 KDateTime end =
dateTime( RoleEndRecurrenceBase );
629 QList<KDateTime> result;
632 if ( !start.isValid() && ! end.isValid() ) {
638 if ( !( start > datetime || end < datetime ) ) {
644 int days = start.daysTo( end );
646 QDate tmpday( datetime.date().addDays( -days - 1 ) );
648 while ( tmpday <= datetime.date() ) {
652 foreach (
const QTime &time, times ) {
653 tmp = KDateTime( tmpday, time, start.timeSpec() );
659 tmpday = tmpday.addDays( 1 );
667 KDateTime end =
dateTime( RoleEndRecurrenceBase );
668 if ( !end.isValid() ) {
671 if ( !start.isValid() ) {
675 return startDt.addSecs( start.secsTo( end ) );
684 Q_ASSERT( !d->mAttachments.contains( attachment ) );
687 d->mAttachments.append( attachment );
694 int index = d->mAttachments.indexOf( attachment );
697 d->mAttachments.remove( index );
704 Attachment::List::Iterator it = d->mAttachments.begin();
705 while ( it != d->mAttachments.end() ) {
706 if ( ( *it )->mimeType() != mime ) {
711 d->mAttachments = result;
717 return d->mAttachments;
724 if ( attachment->mimeType() == mime ) {
725 attachments.append( attachment );
734 d->mAttachments.clear();
739 if ( d->mTempFiles.contains( attachment ) ) {
740 return d->mTempFiles.value( attachment );
742 KTemporaryFile *file =
new KTemporaryFile();
744 QStringList patterns = KMimeType::mimeType( attachment->mimeType() )->patterns();
746 if ( !patterns.empty() ) {
747 file->setSuffix( QString( patterns.first() ).
remove(
'*' ) );
749 file->setAutoRemove(
true );
752 file->setPermissions( QFile::ReadUser );
753 file->write( QByteArray::fromBase64( attachment->data() ) );
754 d->mTempFiles.insert( attachment, file->fileName() );
756 return d->mTempFiles.value( attachment );
761 QHash<Attachment::Ptr,QString>::const_iterator it = d->mTempFiles.constBegin();
762 const QHash<Attachment::Ptr,QString>::const_iterator end = d->mTempFiles.constEnd();
763 for ( ; it != end; ++it ) {
764 QFile::remove( it.value() );
766 d->mTempFiles.clear();
783 return d->mResources;
811 d->mStatusString.clear();
824 d->mStatusString =
status;
837 return d->mStatusString;
868 d->mAlarms.append( alarm );
875 d->mAlarms.append( alarm );
882 const int index = d->mAlarms.indexOf( alarm );
885 d->mAlarms.remove( index );
902 if ( alarm->enabled() ) {
917 d->mLocationIsRich = isRich;
924 setLocation( location, Qt::mightBeRichText( location ) );
937 return Qt::escape( d->mLocation ).replace(
'\n',
"<br/>" );
943 return d->mLocationIsRich;
948 d->mSchedulingID = sid;
949 if ( !uid.isEmpty() ) {
957 if ( d->mSchedulingID.isNull() ) {
961 return d->mSchedulingID;
975 if ( hasGeo == d->mHasGeo ) {
988 return d->mGeoLatitude;
998 d->mGeoLatitude = geolatitude;
1005 return d->mGeoLongitude;
1012 d->mGeoLongitude = geolongitude;
1020 return d->mRecurrenceId.isValid();
1025 return d->mRecurrenceId;
1043 if ( recurrence == d->mRecurrence ) {
1050 #define ALT_DESC_FIELD "X-ALT-DESC"
1051 #define ALT_DESC_PARAMETERS "FMTTYPE=text/html"
1059 return parameter == ALT_DESC_PARAMETERS && !value.isEmpty();
1064 if ( altdescription.isEmpty() ) {
1069 ALT_DESC_PARAMETERS );