39 #include <KTemporaryFile>
42 #include <QTextDocument>
45 using namespace KCalCore;
52 class KCalCore::Incidence::Private
57 mDescriptionIsRich(false),
58 mSummaryIsRich(false),
59 mLocationIsRich(false),
62 mSecrecy(SecrecyPublic),
64 mGeoLatitude(INVALID_LATLON),
65 mGeoLongitude(INVALID_LATLON),
67 mThisAndFuture(false),
72 Private(
const Private &p)
73 : mCreated(p.mCreated),
74 mRevision(p.mRevision),
75 mDescription(p.mDescription),
76 mDescriptionIsRich(p.mDescriptionIsRich),
78 mSummaryIsRich(p.mSummaryIsRich),
79 mLocation(p.mLocation),
80 mLocationIsRich(p.mLocationIsRich),
81 mCategories(p.mCategories),
83 mResources(p.mResources),
85 mStatusString(p.mStatusString),
87 mPriority(p.mPriority),
88 mSchedulingID(p.mSchedulingID),
89 mRelatedToUid(p.mRelatedToUid),
90 mGeoLatitude(p.mGeoLatitude),
91 mGeoLongitude(p.mGeoLongitude),
93 mRecurrenceId(p.mRecurrenceId),
94 mThisAndFuture(p.mThisAndFuture),
102 mAttachments.clear();
109 mRevision = src.d->mRevision;
110 mCreated = src.d->mCreated;
111 mDescription = src.d->mDescription;
112 mSummary = src.d->mSummary;
113 mCategories = src.d->mCategories;
114 mRelatedToUid = src.d->mRelatedToUid;
115 mResources = src.d->mResources;
116 mStatusString = src.d->mStatusString;
117 mStatus = src.d->mStatus;
118 mSecrecy = src.d->mSecrecy;
119 mPriority = src.d->mPriority;
120 mLocation = src.d->mLocation;
121 mGeoLatitude = src.d->mGeoLatitude;
122 mGeoLongitude = src.d->mGeoLongitude;
123 mHasGeo = src.d->mHasGeo;
124 mRecurrenceId = src.d->mRecurrenceId;
125 mThisAndFuture = src.d->mThisAndFuture;
126 mLocalOnly = src.d->mLocalOnly;
139 mAttachments.append(a);
142 if (src.d->mRecurrence) {
143 mRecurrence =
new Recurrence(*(src.d->mRecurrence));
144 mRecurrence->addObserver(dest);
153 QString mDescription;
154 bool mDescriptionIsRich;
158 bool mLocationIsRich;
159 QStringList mCategories;
163 QStringList mResources;
165 QString mStatusString;
168 QString mSchedulingID;
170 QMap<RelType,QString> mRelatedToUid;
174 QHash<Attachment::Ptr,QString> mTempFiles;
175 KDateTime mRecurrenceId;
191 d(new KCalCore::
Incidence::Private(*i.d))
205 delete d->mRecurrence;
211 static bool stringCompare(
const QString &s1,
const QString &s2)
213 return (s1.isEmpty() && s2.isEmpty()) || (s1 == s2);
219 if (&other !=
this) {
243 Alarm::List::ConstIterator a1 =
alarms().constBegin();
244 Alarm::List::ConstIterator a1end =
alarms().constEnd();
245 Alarm::List::ConstIterator a2 = i2->
alarms().constBegin();
246 Alarm::List::ConstIterator a2end = i2->
alarms().constEnd();
247 for (; a1 != a1end && a2 != a2end; ++a1, ++a2) {
259 Attachment::List::ConstIterator att1 =
attachments().constBegin();
260 const Attachment::List::ConstIterator att1end =
attachments().constEnd();
261 Attachment::List::ConstIterator att2 = i2->
attachments().constBegin();
262 const Attachment::List::ConstIterator att2end = i2->
attachments().constEnd();
263 for (; att1 != att1end && att2 != att2end; ++att1, ++att2) {
264 if (**att1 == **att2) {
271 bool recurrenceEqual = (d->mRecurrence == 0 && i2->d->mRecurrence == 0);
272 if (!recurrenceEqual) {
275 recurrenceEqual = d->mRecurrence != 0 &&
276 i2->d->mRecurrence != 0 &&
277 *d->mRecurrence == *i2->d->mRecurrence;
288 d->mStatus == i2->d->mStatus &&
290 stringCompare(d->mStatusString, i2->d->mStatusString)) &&
309 const KDateTime nowUTC = KDateTime::currentUtcDateTime();
319 if (!d->mLocalOnly) {
327 if (d->mRecurrence) {
328 d->mRecurrence->setRecurReadOnly(readOnly);
342 return d->mLocalOnly;
350 if (d->mRecurrence) {
351 d->mRecurrence->setAllDay(allDay);
362 d->mCreated = created.toUtc();
394 if (d->mRecurrence) {
395 d->mRecurrence->setStartDateTime(dt);
401 const KDateTime::Spec &newSpec)
404 if (d->mRecurrence) {
405 d->mRecurrence->shiftTimes(oldSpec, newSpec);
407 for (
int i = 0, end = d->mAlarms.count(); i < end; ++i) {
408 d->mAlarms[i]->shiftTimes(oldSpec, newSpec);
419 d->mDescriptionIsRich = isRich;
431 return d->mDescription;
437 return d->mDescription;
439 return Qt::escape(d->mDescription).replace(
'\n',
"<br/>");
445 return d->mDescriptionIsRich;
455 d->mSummaryIsRich = isRich;
462 setSummary(summary, Qt::mightBeRichText(summary));
475 return Qt::escape(d->mSummary).replace(
'\n',
"<br/>");
481 return d->mSummaryIsRich;
503 d->mCategories.clear();
505 if (catStr.isEmpty()) {
510 d->mCategories = catStr.split(
',');
512 QStringList::Iterator it;
513 for (it = d->mCategories.begin(); it != d->mCategories.end(); ++it) {
514 *it = (*it).trimmed();
522 return d->mCategories;
527 return d->mCategories.join(
",");
535 if (d->mRelatedToUid[relType] != relatedToUid) {
537 d->mRelatedToUid[relType] = relatedToUid;
545 return d->mRelatedToUid.value(relType);
552 if (!d->mRecurrence) {
555 d->mRecurrence->setAllDay(
allDay());
556 d->mRecurrence->setRecurReadOnly(
mReadOnly);
557 d->mRecurrence->addObserver(const_cast<KCalCore::Incidence*>(
this));
560 return d->mRecurrence;
565 delete d->mRecurrence;
571 if (d->mRecurrence) {
572 return d->mRecurrence->recurrenceType();
574 return Recurrence::rNone;
580 if (d->mRecurrence) {
581 return d->mRecurrence->recurs();
588 const KDateTime::Spec &timeSpec)
const
590 return d->mRecurrence && d->mRecurrence->recursOn(date, timeSpec);
595 return d->mRecurrence && d->mRecurrence->recursAt(qdt);
599 const KDateTime::Spec &timeSpec)
const
602 KDateTime end =
dateTime(RoleEndRecurrenceBase);
604 QList<KDateTime> result;
607 if (!start.isValid() && ! end.isValid()) {
612 KDateTime kdate(date, timeSpec);
614 if (!(start > kdate || end < kdate)) {
620 int days = start.daysTo(end);
622 QDate tmpday(date.addDays(-days - 1));
624 while (tmpday <= date) {
627 foreach(
const QTime &time, times) {
628 tmp = KDateTime(tmpday, time, start.timeSpec());
634 tmpday = tmpday.addDays(1);
642 KDateTime end =
dateTime(RoleEndRecurrenceBase);
644 QList<KDateTime> result;
647 if (!start.isValid() && ! end.isValid()) {
653 if (!(start > datetime || end < datetime)) {
659 int days = start.daysTo(end);
661 QDate tmpday(datetime.date().addDays(-days - 1));
663 while (tmpday <= datetime.date()) {
667 foreach(
const QTime &time, times) {
668 tmp = KDateTime(tmpday, time, start.timeSpec());
674 tmpday = tmpday.addDays(1);
682 KDateTime end =
dateTime(RoleEndRecurrenceBase);
683 if (!end.isValid()) {
686 if (!start.isValid()) {
690 return startDt.addSecs(start.secsTo(end));
699 Q_ASSERT(!d->mAttachments.contains(attachment));
702 d->mAttachments.append(attachment);
709 int index = d->mAttachments.indexOf(attachment);
712 d->mAttachments.remove(index);
719 Attachment::List::Iterator it = d->mAttachments.begin();
720 while (it != d->mAttachments.end()) {
721 if ((*it)->mimeType() != mime) {
726 d->mAttachments = result;
732 return d->mAttachments;
739 if (attachment->mimeType() == mime) {
740 attachments.append(attachment);
749 d->mAttachments.clear();
754 if (d->mTempFiles.contains(attachment)) {
755 return d->mTempFiles.value(attachment);
757 KTemporaryFile *file =
new KTemporaryFile();
759 QStringList patterns = KMimeType::mimeType(attachment->mimeType())->patterns();
761 if (!patterns.empty()) {
762 file->setSuffix(QString(patterns.first()).
remove(
'*'));
764 file->setAutoRemove(
true);
767 file->setPermissions(QFile::ReadUser);
768 file->write(QByteArray::fromBase64(attachment->data()));
769 d->mTempFiles.insert(attachment, file->fileName());
771 return d->mTempFiles.value(attachment);
776 QHash<Attachment::Ptr,QString>::const_iterator it = d->mTempFiles.constBegin();
777 const QHash<Attachment::Ptr,QString>::const_iterator end = d->mTempFiles.constEnd();
778 for (; it != end; ++it) {
779 QFile::remove(it.value());
781 d->mTempFiles.clear();
798 return d->mResources;
826 d->mStatusString.clear();
839 d->mStatusString =
status;
852 return d->mStatusString;
883 d->mAlarms.append(alarm);
890 d->mAlarms.append(alarm);
897 const int index = d->mAlarms.indexOf(alarm);
900 d->mAlarms.remove(index);
917 if (alarm->enabled()) {
932 d->mLocationIsRich = isRich;
939 setLocation(location, Qt::mightBeRichText(location));
952 return Qt::escape(d->mLocation).replace(
'\n',
"<br/>");
958 return d->mLocationIsRich;
963 d->mSchedulingID = sid;
964 if (!uid.isEmpty()) {
972 if (d->mSchedulingID.isNull()) {
976 return d->mSchedulingID;
990 if (hasGeo == d->mHasGeo) {
1003 return d->mGeoLatitude;
1013 d->mGeoLatitude = geolatitude;
1020 return d->mGeoLongitude;
1027 d->mGeoLongitude = geolongitude;
1035 return d->mRecurrenceId.isValid();
1040 return d->mRecurrenceId;
1050 return d->mThisAndFuture;
1068 if (recurrence == d->mRecurrence) {
1075 #define ALT_DESC_FIELD "X-ALT-DESC"
1076 #define ALT_DESC_PARAMETERS "FMTTYPE=text/html"
1084 return parameter == ALT_DESC_PARAMETERS && !value.isEmpty();
1089 if (altdescription.isEmpty()) {
1094 ALT_DESC_PARAMETERS);