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>
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));
78class KCalCore::VCalFormat::Private
90#if defined(KCALCORE_FOR_SYMBIAN)
105 d->mCalendar = calendar;
136 d->mCalendar = calendar;
151 Todo::List::ConstIterator
it;
153 if ((*it)->dtStart().timeZone().name().mid(0, 4) ==
QLatin1String(
"VCAL")) {
155 if (zone.isValid()) {
159 while (!
dst.isEmpty()) {
170 Event::List::ConstIterator
it2;
171 for (
it2 = events.constBegin();
it2 != events.constEnd(); ++
it2) {
172 if ((*it2)->dtStart().timeZone().name().mid(0, 4) ==
QLatin1String(
"VCAL")) {
174 if (zone.isValid()) {
178 while (!
dst.isEmpty()) {
191 if (QFile::exists(fileName)) {
201 bool deleted,
const QString ¬ebook)
207 bool deleted,
const QString ¬ebook)
209 d->mCalendar = calendar;
211 if (!
string.size()) {
236 const QString ¬ebook,
bool deleted)
239 d->mCalendar = calendar;
251 Todo::List::ConstIterator
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) ==
QLatin1String(
"VCAL")) {
260 if (zone.isValid()) {
264 while (!
dst.isEmpty()) {
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) ==
QLatin1String(
"VCAL")) {
287 if (zone.isValid()) {
291 while (!
dst.isEmpty()) {
351 if (!
anEvent->organizer()->email().isEmpty()) {
357 if (
anEvent->attendeeCount() > 0) {
358 Attendee::List::ConstIterator
it;
367 kDebug() <<
"warning! this Event has an attendee w/o name or email!";
381 if (
recur->recurs()) {
384 switch (
recur->recurrenceType()) {
385 case Recurrence::rDaily:
388 case Recurrence::rWeekly:
390 for (
int i = 0;
i < 7; ++
i) {
392 if (days.testBit(
i)) {
397 case Recurrence::rMonthlyPos:
402 for (QList<RecurrenceRule::WDayPos>::ConstIterator
posit =
tmpPositions.constBegin();
404 int pos = (*posit).pos();
405 tmpStr2.sprintf(
"%i", (pos > 0) ? pos : (-pos));
416 case Recurrence::rMonthlyDay:
421 for (QList<int>::ConstIterator
tmpDay =
tmpDays.constBegin();
428 case Recurrence::rYearlyMonth:
434 for (QList<int>::ConstIterator
mit =
months.constBegin();
441 case Recurrence::rYearlyDay:
455 kDebug() <<
"ERROR, it should never get here in eventToVTodo!";
460 if (
recur->duration() > 0) {
463 }
else if (
recur->duration() == -1) {
478 DateList::ConstIterator
id;
491 DateTimeList::ConstIterator
idt;
504 if (!
anEvent->description().isEmpty()) {
507 KCodecs::quotedPrintableEncode(
in,
out,
true);
518 if (!
anEvent->summary().isEmpty()) {
521 KCodecs::quotedPrintableEncode(
in,
out,
true);
532 if (!
anEvent->location().isEmpty()) {
535 KCodecs::quotedPrintableEncode(
in,
out,
true);
550 if (
anEvent->hasCompletedDate()) {
560 if (!
anEvent->relatedTo().isEmpty()) {
562 anEvent->relatedTo().toUtf8());
566 const char *text = 0;
575 text =
"CONFIDENTIAL";
586 QStringList::const_iterator
its;
605 Alarm::List::ConstIterator
it;
608 if (
alarm->enabled()) {
615 if (
alarm->text().isNull()) {
643#if defined(KCALCORE_FOR_SYMBIAN)
667#if !defined(KCALCORE_FOR_MEEGO)
698 if (!
anEvent->organizer()->email().isEmpty()) {
704 if (
anEvent->attendeeCount() > 0) {
705 Attendee::List::ConstIterator
it;
713 kDebug() <<
"warning! this Event has an attendee w/o name or email!";
727 if (
recur->recurs()) {
730 switch (
recur->recurrenceType()) {
731 case Recurrence::rDaily:
734 case Recurrence::rWeekly:
736 for (
int i = 0;
i < 7; ++
i) {
738 if (days.testBit(
i)) {
743 case Recurrence::rMonthlyPos:
748 for (QList<RecurrenceRule::WDayPos>::ConstIterator
posit =
tmpPositions.constBegin();
750 int pos = (*posit).pos();
751 tmpStr2.sprintf(
"%i", (pos > 0) ? pos : (-pos));
762 case Recurrence::rMonthlyDay:
767 for (QList<int>::ConstIterator
tmpDay =
tmpDays.constBegin();
774 case Recurrence::rYearlyMonth:
780 for (QList<int>::ConstIterator
mit =
months.constBegin();
787 case Recurrence::rYearlyDay:
801 kDebug() <<
"ERROR, it should never get here in eventToVEvent!";
806 if (
recur->duration() > 0) {
809 }
else if (
recur->duration() == -1) {
812#if !defined(KCALCORE_FOR_MEEGO)
829 DateList::ConstIterator
it;
842 DateTimeList::ConstIterator
idt;
855 if (!
anEvent->description().isEmpty()) {
858 KCodecs::quotedPrintableEncode(
in,
out,
true);
869 if (!
anEvent->summary().isEmpty()) {
872 KCodecs::quotedPrintableEncode(
in,
out,
true);
883 if (!
anEvent->location().isEmpty()) {
886 KCodecs::quotedPrintableEncode(
in,
out,
true);
901 const char *text = 0;
910 text =
"CONFIDENTIAL";
942 Attachment::List::ConstIterator
atIt;
943 for (
atIt = attachments.constBegin();
atIt != attachments.constEnd(); ++
atIt) {
955 Alarm::List::ConstIterator
it2;
958 if (
alarm->enabled()) {
965 if (
alarm->text().isNull()) {
996 if (!
anEvent->relatedTo().isEmpty()) {
1008#if defined(KCALCORE_FOR_SYMBIAN)
1019 if (
anEvent->hasRecurrenceId()) {
1057 anEvent->setLastModified(KDateTime::currentUtcDateTime());
1066 if (
d->mCalendar->owner()->name() !=
QLatin1String(
"Unknown Name")) {
1067 anEvent->setOrganizer(
d->mCalendar->owner());
1079 QString
tmpStr = QString::fromUtf8(
s);
1095 QString email =
tmpStr.replace(
' ',
'.');
1115 anEvent->setDescription(QString::fromUtf8(
s), Qt::mightBeRichText(
s));
1122 anEvent->setSummary(QString::fromUtf8(
s), Qt::mightBeRichText(
s));
1129 anEvent->setLocation(QString::fromUtf8(
s), Qt::mightBeRichText(
s));
1137 if (
s &&
strcmp(
s,
"COMPLETED") == 0) {
1168 if (
anEvent->dtDue().time().hour() == 0 &&
1169 anEvent->dtDue().time().minute() == 0 &&
1170 anEvent->dtDue().time().second() == 0) {
1171#if defined(KCALCORE_FOR_MEEGO)
1185 if (
anEvent->dtStart().time().hour() == 0 &&
1186 anEvent->dtStart().time().minute() == 0 &&
1187 anEvent->dtStart().time().second() == 0) {
1188#if defined(KCALCORE_FOR_MEEGO)
1206 uint type = Recurrence::rNone;
1207 if (
tmpStr.left(1) ==
"D") {
1208 type = Recurrence::rDaily;
1209 }
else if (
tmpStr.left(1) ==
"W") {
1210 type = Recurrence::rWeekly;
1213 if (
tmpStr.left(2) ==
"MP") {
1214 type = Recurrence::rMonthlyPos;
1215 }
else if (
tmpStr.left(2) ==
"MD") {
1216 type = Recurrence::rMonthlyDay;
1217 }
else if (
tmpStr.left(2) ==
"YM") {
1218 type = Recurrence::rYearlyMonth;
1219 }
else if (
tmpStr.left(2) ==
"YD") {
1220 type = Recurrence::rYearlyDay;
1224 if (type != Recurrence::rNone) {
1227 int index =
tmpStr.indexOf(
' ');
1234 case Recurrence::rDaily:
1238 case Recurrence::rWeekly:
1242 if (index ==
last) {
1244 qba.setBit(
anEvent->dtStart().date().dayOfWeek() - 1);
1247 while (index <
last) {
1260 case Recurrence::rMonthlyPos:
1266 if (index ==
last) {
1272 qba.setBit(
anEvent->dtStart().date().dayOfWeek() - 1);
1276 while (index <
last) {
1279 if (
tmpStr.mid(index, 1) ==
"-") {
1297 case Recurrence::rMonthlyDay:
1299 if (index ==
last) {
1305 while (index <
last) {
1313 if (
tmpStr.mid(index, 1) ==
"-") {
1322 case Recurrence::rYearlyMonth:
1325 if (index ==
last) {
1331 while (index <
last) {
1340 case Recurrence::rYearlyDay:
1343 if (index ==
last) {
1349 while (index <
last) {
1364 if (
tmpStr.mid(index, 1) ==
"#") {
1371 }
else if (
tmpStr.indexOf(
'T', index) != -1) {
1376 kDebug() <<
"we don't understand this type of recurrence!";
1383 QStringList exDates = QString::fromUtf8(
s).split(
',');
1384 QStringList::ConstIterator
it;
1385 for (
it = exDates.constBegin();
it != exDates.constEnd(); ++
it) {
1387 if (
exDate.time().hour() == 0 &&
1388 exDate.time().minute() == 0 &&
1389 exDate.time().second() == 0) {
1412 alarm->setEnabled(
true);
1415 alarm->setDisplayAlarm(QString(
s));
1418 alarm->setDisplayAlarm(QString());
1436 alarm->setEnabled(
true);
1439 alarm->setAudioAlarm(QFile::decodeName(
s));
1442 alarm->setAudioAlarm(QString());
1460 alarm->setEnabled(
true);
1464 alarm->setProcedureAlarm(QFile::decodeName(
s));
1467 alarm->setProcedureAlarm(QString());
1483 if (
s &&
strcmp(
s,
"PRIVATE") == 0) {
1485 }
else if (
s &&
strcmp(
s,
"CONFIDENTIAL") == 0) {
1495 QString categories = QString::fromUtf8(
s);
1497 QStringList
tmpStrList = categories.split(
';');
1503 anEvent->setNonKDECustomProperty(
1507 anEvent->setNonKDECustomProperty(
1541#if defined(KCALCORE_FOR_SYMBIAN)
1566 anEvent->setLastModified(KDateTime::currentUtcDateTime());
1576 if (
d->mCalendar->owner()->name() !=
"Unknown Name") {
1577 anEvent->setOrganizer(
d->mCalendar->owner());
1589 QString
tmpStr = QString::fromUtf8(
s);
1599 }
else if (
tmpStr.indexOf(
'@') > 0) {
1604 QString email =
tmpStr.replace(
' ',
'.');
1637 if (
anEvent->dtStart().time().hour() == 0 &&
1638 anEvent->dtStart().time().minute() == 0 &&
1639 anEvent->dtStart().time().second() == 0) {
1640#if defined(KCALCORE_FOR_MEEGO)
1653 if (
anEvent->dtEnd().time().hour() == 0 &&
1654 anEvent->dtEnd().time().minute() == 0 &&
1655 anEvent->dtEnd().time().second() == 0) {
1656#if defined(KCALCORE_FOR_MEEGO)
1663#if defined(KCALCORE_FOR_MEEGO)
1690 uint type = Recurrence::rNone;
1691 if (
tmpStr.left(1) ==
"D") {
1692 type = Recurrence::rDaily;
1693 }
else if (
tmpStr.left(1) ==
"W") {
1694 type = Recurrence::rWeekly;
1697 if (
tmpStr.left(2) ==
"MP") {
1698 type = Recurrence::rMonthlyPos;
1699 }
else if (
tmpStr.left(2) ==
"MD") {
1700 type = Recurrence::rMonthlyDay;
1701 }
else if (
tmpStr.left(2) ==
"YM") {
1702 type = Recurrence::rYearlyMonth;
1703 }
else if (
tmpStr.left(2) ==
"YD") {
1704 type = Recurrence::rYearlyDay;
1708 if (type != Recurrence::rNone) {
1711 int index =
tmpStr.indexOf(
' ');
1718 case Recurrence::rDaily:
1722 case Recurrence::rWeekly:
1726 if (index ==
last) {
1728 qba.setBit(
anEvent->dtStart().date().dayOfWeek() - 1);
1731 while (index <
last) {
1744 case Recurrence::rMonthlyPos:
1750 if (index ==
last) {
1756 qba.setBit(
anEvent->dtStart().date().dayOfWeek() - 1);
1760 while (index <
last) {
1763 if (
tmpStr.mid(index, 1) ==
"-") {
1781 case Recurrence::rMonthlyDay:
1783 if (index ==
last) {
1789 while (index <
last) {
1797 if (
tmpStr.mid(index, 1) ==
"-") {
1806 case Recurrence::rYearlyMonth:
1809 if (index ==
last) {
1815 while (index <
last) {
1824 case Recurrence::rYearlyDay:
1827 if (index ==
last) {
1833 while (index <
last) {
1848 if (
tmpStr.mid(index, 1) ==
"#") {
1855 }
else if (
tmpStr.indexOf(
'T', index) != -1) {
1862 kDebug() <<
"we don't understand this type of recurrence!";
1869 QStringList exDates = QString::fromUtf8(
s).split(
',');
1870 QStringList::ConstIterator
it;
1871 for (
it = exDates.constBegin();
it != exDates.constEnd(); ++
it) {
1873 if (
exDate.time().hour() == 0 &&
1874 exDate.time().minute() == 0 &&
1875 exDate.time().second() == 0) {
1887 anEvent->setSummary(QString::fromUtf8(
s), Qt::mightBeRichText(
s));
1894 bool isRich = Qt::mightBeRichText(
s);
1895 if (!
anEvent->description().isEmpty()) {
1907 anEvent->setLocation(QString::fromUtf8(
s), Qt::mightBeRichText(
s));
1913 if (
anEvent->summary().isEmpty() && !(
anEvent->description().isEmpty())) {
1935 if (
s &&
strcmp(
s,
"PRIVATE") == 0) {
1937 }
else if (
s &&
strcmp(
s,
"CONFIDENTIAL") == 0) {
1947 QString categories = QString::fromUtf8(
s);
1949 QStringList
tmpStrList = categories.split(
',');
1968 QStringList
tmpStrList = resources.split(
';');
1986 alarm->setEnabled(
true);
1990 alarm->setDisplayAlarm(QString(
s));
1993 alarm->setDisplayAlarm(QString());
2011 alarm->setEnabled(
true);
2015 alarm->setAudioAlarm(QFile::decodeName(
s));
2018 alarm->setAudioAlarm(QString());
2036 alarm->setEnabled(
true);
2040 alarm->setProcedureAlarm(QFile::decodeName(
s));
2043 alarm->setProcedureAlarm(QString());
2076 anEvent->setNonKDECustomProperty(
2080 anEvent->setNonKDECustomProperty(
2103 if (!
timezone.contains(
"BEGIN:DAYLIGHT")) {
2114 sOffset.insert(3, QString(
":"));
2126 if (!
qd.isValid()) {
2130 tmpStr.sprintf(
"%.2d%.2d%.2d",
qd.year(),
qd.month(),
qd.day());
2139 if (!
dt.isValid()) {
2145 tmpDT =
dt.toUtc().dateTime();
2147#if !defined(KCALCORE_FOR_MEEGO)
2148 tmpDT =
dt.toTimeSpec(
d->mCalendar->timeSpec()).dateTime();
2153 tmpStr.sprintf(
"%.2d%.2d%.2dT%.2d%.2d%.2d",
2156 tmpDT.time().minute(),
tmpDT.time().second());
2157 if (
zulu ||
dt.isUtc()) {
2173 day =
tmpStr.mid(6, 2).toInt();
2198 day =
dateStr.mid(6, 2).toInt();
2213 QString
str =
s.trimmed();
2224 }
else if (
str[
ofs] ==
'+') {
2234 if (
str.size() < (
ofs + 2)) {
2249 if (
str.size() < (
ofs + 2)) {
2288 kDebug() <<
"This vCalendar file was not created by KOrganizer or"
2289 <<
"any other product we support. Loading anyway...";
2298 if (!
s ||
strcmp(_VCAL_VERSION,
s) != 0) {
2299 kDebug() <<
"This vCalendar file has version" <<
s
2300 <<
"We only support" << _VCAL_VERSION;
2326 tz = QString(
"STD;%1;false;%2").arg(QString::number(
utcOffset)).arg(
dt.toString());
2340 if (
argl.size() < 4) {
2364 if (endDate < startDate) {
2370 tz = QString::fromLatin1(
"%1;%2;false;%3").
2376 tz = QString::fromLatin1(
"%1;%2;true;%3").
2382 kDebug() <<
"unable to parse dst" <<
argl[1];
2389 if (!zone.isValid()) {
2390 kDebug() <<
"zone is not valid, parsing error" <<
tzList;
2393 d->mCalendar->setTimeZoneId(name);
2397 kDebug() <<
"unable to parse tzoffset" <<
ts;
2402 d->mEventsRelate.clear();
2403 d->mTodosRelate.clear();
2421 if (
atoi(
s) == SYNCDEL) {
2423 kDebug() <<
"skipping pilot-deleted event";
2432 kDebug() <<
"found a VEvent with no DTSTART and no DTEND! Skipping...";
2445 d->mCalendar->timeSpec());
2447 d->mCalendar->timeSpec());
2452 d->mCalendar->event(
anEvent->uid()) :
2457 d->mCalendar->deleteEvent(
old);
2459 }
else if (
anEvent->revision() >
old->revision()) {
2460 d->mCalendar->deleteEvent(
old);
2464 }
else if (deleted) {
2466 d->mCalendar->deletedEvent(
anEvent->uid()) :
2470 d->mCalendar->deleteEvent(
anEvent);
2486 d->mCalendar->timeSpec());
2487 aTodo->setDtStart(dtStart);
2488 if (
aTodo->hasDueDate()) {
2490 d->mCalendar->timeSpec());
2491 aTodo->setDtDue(dtDue);
2495 d->mCalendar->todo(
aTodo->uid()) :
2496 d->mCalendar->todo(
aTodo->uid(),
aTodo->recurrenceId());
2499 d->mCalendar->deleteTodo(
old);
2501 }
else if (
aTodo->revision() >
old->revision()) {
2502 d->mCalendar->deleteTodo(
old);
2504 d->mCalendar->addTodo(
aTodo);
2506 }
else if (deleted) {
2507 old =
d->mCalendar->deletedTodo(
aTodo->uid(),
aTodo->recurrenceId());
2509 d->mCalendar->addTodo(
aTodo);
2510 d->mCalendar->deleteTodo(
aTodo);
2513 d->mCalendar->addTodo(
aTodo);
2533 Event::List::ConstIterator
eIt;
2534 for (
eIt =
d->mEventsRelate.constBegin();
eIt !=
d->mEventsRelate.constEnd(); ++
eIt) {
2535 (*eIt)->setRelatedTo((*eIt)->relatedTo());
2537 Todo::List::ConstIterator
tIt;
2538 for (
tIt =
d->mTodosRelate.constBegin();
tIt !=
d->mTodosRelate.constEnd(); ++
tIt) {
2539 (*tIt)->setRelatedTo((*tIt)->relatedTo());
2551 const char *days[7] = {
"MO ",
"TU ",
"WE ",
"TH ",
"FR ",
"SA ",
"SU " };
2608 kDebug() <<
"error setting attendee mStatus, unknown mStatus!";
2620 return "NEEDS ACTION";
2638 return "NEEDS ACTION";
2659 i->setNonKDECustomProperty(
2669 for (QMap<QByteArray, QString>::ConstIterator
c =
custom.begin();
2671 if (
d->mManuallyWrittenExtensionFields.contains(
c.key()) ||
2672 c.key().startsWith(
"X-KDE-VOLATILE")) {
This file is part of the API for handling calendar data and defines the Calendar class.
QSharedPointer< Alarm > Ptr
A shared pointer to an Alarm object.
@ Display
Display a dialog box.
@ Audio
Play an audio file.
@ Procedure
Call a script.
Represents information related to an attachment for a Calendar Incidence.
QVector< Ptr > List
List of attachments.
QSharedPointer< Attachment > Ptr
A shared pointer to an Attachment object.
Represents information related to an attendee of an Calendar Incidence, typically a meeting or task (...
PartStat
The different types of participant status.
@ InProcess
To-do in process of being completed.
@ Tentative
Event or to-do tentatively accepted.
@ Accepted
Event, to-do or journal accepted.
@ Delegated
Event or to-do delegated.
@ NeedsAction
Event, to-do or journal needs action (default)
@ Declined
Event, to-do or journal declined.
@ Completed
To-do completed.
QSharedPointer< Attendee > Ptr
A shared pointer to an Attendee object.
QSharedPointer< Calendar > Ptr
A shared pointer to a Calendar.
This class provides an Event in the sense of RFC2445.
@ Transparent
Event does not appear in free/busy time.
@ Opaque
Event appears in free/busy time.
QSharedPointer< Event > Ptr
A shared pointer to an Event object.
QVector< Ptr > List
List of events.
Exception base class, currently used as a fancy kind of error code and not as an C++ exception.
@ CalVersionUnknown
Unknown calendar format detected.
A class which reads and parses iCalendar VTIMEZONE components, and accesses libical time zone data.
The ICalTimeZone class represents an iCalendar VTIMEZONE component.
QByteArray vtimezone() const
Returns the VTIMEZONE string which represents this time zone.
The ICalTimeZones class represents a time zone database which consists of a collection of individual ...
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)
QSharedPointer< Incidence > Ptr
A shared pointer to an Incidence.
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.
QVector< Ptr > List
List of to-dos.
QSharedPointer< Todo > Ptr
A shared pointer to a Todo object.
This file is part of the API for handling calendar data and defines the Event class.
This file is part of the API for handling calendar data and defines the Exception class.
static uint qHash(const KDateTime &dt)
Private class that helps to provide binary compatibility between releases.
This file is part of the API for handling calendar data and defines the Todo class.