Changeset View
Changeset View
Standalone View
Standalone View
src/recurrence.cpp
Show All 16 Lines | 1 | /* | |||
---|---|---|---|---|---|
17 | Library General Public License for more details. | 17 | Library General Public License for more details. | ||
18 | 18 | | |||
19 | You should have received a copy of the GNU Library General Public License | 19 | You should have received a copy of the GNU Library General Public License | ||
20 | along with this library; see the file COPYING.LIB. If not, write to | 20 | along with this library; see the file COPYING.LIB. If not, write to | ||
21 | the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | 21 | the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
22 | Boston, MA 02110-1301, USA. | 22 | Boston, MA 02110-1301, USA. | ||
23 | */ | 23 | */ | ||
24 | #include "recurrence.h" | 24 | #include "recurrence.h" | ||
25 | #include "sortablelist.h" | | |||
26 | #include "utils.h" | 25 | #include "utils.h" | ||
27 | #include "recurrencehelper_p.h" | 26 | #include "recurrencehelper_p.h" | ||
28 | 27 | | |||
29 | #include "kcalcore_debug.h" | 28 | #include "kcalcore_debug.h" | ||
30 | 29 | | |||
30 | #include <QDataStream> | ||||
31 | #include <QTimeZone> | 31 | #include <QTimeZone> | ||
32 | #include <QBitArray> | 32 | #include <QBitArray> | ||
33 | #include <QTime> | 33 | #include <QTime> | ||
34 | 34 | | |||
35 | using namespace KCalCore; | 35 | using namespace KCalCore; | ||
36 | 36 | | |||
37 | //@cond PRIVATE | 37 | //@cond PRIVATE | ||
38 | class Q_DECL_HIDDEN KCalCore::Recurrence::Private | 38 | class Q_DECL_HIDDEN KCalCore::Recurrence::Private | ||
Show All 17 Lines | 49 | : mRDateTimes(p.mRDateTimes), | |||
56 | mRecurReadOnly(p.mRecurReadOnly) | 56 | mRecurReadOnly(p.mRecurReadOnly) | ||
57 | { | 57 | { | ||
58 | } | 58 | } | ||
59 | 59 | | |||
60 | bool operator==(const Private &p) const; | 60 | bool operator==(const Private &p) const; | ||
61 | 61 | | |||
62 | RecurrenceRule::List mExRules; | 62 | RecurrenceRule::List mExRules; | ||
63 | RecurrenceRule::List mRRules; | 63 | RecurrenceRule::List mRRules; | ||
64 | SortableList<QDateTime> mRDateTimes; | 64 | QList<QDateTime> mRDateTimes; | ||
65 | DateList mRDates; | 65 | DateList mRDates; | ||
66 | SortableList<QDateTime> mExDateTimes; | 66 | QList<QDateTime> mExDateTimes; | ||
67 | DateList mExDates; | 67 | DateList mExDates; | ||
68 | QDateTime mStartDateTime; // date/time of first recurrence | 68 | QDateTime mStartDateTime; // date/time of first recurrence | ||
69 | QList<RecurrenceObserver *> mObservers; | 69 | QList<RecurrenceObserver *> mObservers; | ||
70 | 70 | | |||
71 | // Cache the type of the recurrence with the old system (e.g. MonthlyPos) | 71 | // Cache the type of the recurrence with the old system (e.g. MonthlyPos) | ||
72 | mutable ushort mCachedType; | 72 | mutable ushort mCachedType; | ||
73 | 73 | | |||
74 | bool mAllDay = false; // the recurrence has no time, just a date | 74 | bool mAllDay = false; // the recurrence has no time, just a date | ||
▲ Show 20 Lines • Show All 348 Lines • ▼ Show 20 Line(s) | 397 | { | |||
423 | return false; | 423 | return false; | ||
424 | } | 424 | } | ||
425 | 425 | | |||
426 | /** Calculates the cumulative end of the whole recurrence (rdates and rrules). | 426 | /** Calculates the cumulative end of the whole recurrence (rdates and rrules). | ||
427 | If any rrule is infinite, or the recurrence doesn't have any rrules or | 427 | If any rrule is infinite, or the recurrence doesn't have any rrules or | ||
428 | rdates, an invalid date is returned. */ | 428 | rdates, an invalid date is returned. */ | ||
429 | QDateTime Recurrence::endDateTime() const | 429 | QDateTime Recurrence::endDateTime() const | ||
430 | { | 430 | { | ||
431 | SortableList<QDateTime> dts; | 431 | QList<QDateTime> dts; | ||
432 | dts << startDateTime(); | 432 | dts << startDateTime(); | ||
433 | if (!d->mRDates.isEmpty()) { | 433 | if (!d->mRDates.isEmpty()) { | ||
434 | dts << QDateTime(d->mRDates.last(), QTime(0, 0, 0), d->mStartDateTime.timeZone()); | 434 | dts << QDateTime(d->mRDates.last(), QTime(0, 0, 0), d->mStartDateTime.timeZone()); | ||
435 | } | 435 | } | ||
436 | if (!d->mRDateTimes.isEmpty()) { | 436 | if (!d->mRDateTimes.isEmpty()) { | ||
437 | dts << d->mRDateTimes.last(); | 437 | dts << d->mRDateTimes.last(); | ||
438 | } | 438 | } | ||
439 | for (int i = 0, end = d->mRRules.count(); i < end; ++i) { | 439 | for (int i = 0, end = d->mRRules.count(); i < end; ++i) { | ||
▲ Show 20 Lines • Show All 608 Lines • ▼ Show 20 Line(s) | 1047 | for (i = 0, end = d->mExRules.count(); i < end; ++i) { | |||
1048 | extimes += d->mExRules[i]->recurTimesOn(date, timeZone); | 1048 | extimes += d->mExRules[i]->recurTimesOn(date, timeZone); | ||
1049 | } | 1049 | } | ||
1050 | } | 1050 | } | ||
1051 | sortAndRemoveDuplicates(extimes); | 1051 | sortAndRemoveDuplicates(extimes); | ||
1052 | inplaceSetDifference(times, extimes); | 1052 | inplaceSetDifference(times, extimes); | ||
1053 | return times; | 1053 | return times; | ||
1054 | } | 1054 | } | ||
1055 | 1055 | | |||
1056 | SortableList<QDateTime> Recurrence::timesInInterval(const QDateTime &start, const QDateTime &end) const | 1056 | QList<QDateTime> Recurrence::timesInInterval(const QDateTime &start, const QDateTime &end) const | ||
1057 | { | 1057 | { | ||
1058 | int i, count; | 1058 | int i, count; | ||
1059 | SortableList<QDateTime> times; | 1059 | QList<QDateTime> times; | ||
1060 | for (i = 0, count = d->mRRules.count(); i < count; ++i) { | 1060 | for (i = 0, count = d->mRRules.count(); i < count; ++i) { | ||
1061 | times += d->mRRules[i]->timesInInterval(start, end); | 1061 | times += d->mRRules[i]->timesInInterval(start, end); | ||
1062 | } | 1062 | } | ||
1063 | 1063 | | |||
1064 | // add rdatetimes that fit in the interval | 1064 | // add rdatetimes that fit in the interval | ||
1065 | for (i = 0, count = d->mRDateTimes.count(); i < count; ++i) { | 1065 | for (i = 0, count = d->mRDateTimes.count(); i < count; ++i) { | ||
1066 | if (d->mRDateTimes[i] >= start && d->mRDateTimes[i] <= end) { | 1066 | if (d->mRDateTimes[i] >= start && d->mRDateTimes[i] <= end) { | ||
1067 | times += d->mRDateTimes[i]; | 1067 | times += d->mRDateTimes[i]; | ||
Show All 30 Lines | 1097 | for (i = 0, count = d->mExDates.count(); i < count && idt < enddt; ++i) { | |||
1098 | while (idt < enddt && times[idt].date() < d->mExDates[i]) { | 1098 | while (idt < enddt && times[idt].date() < d->mExDates[i]) { | ||
1099 | ++idt; | 1099 | ++idt; | ||
1100 | } | 1100 | } | ||
1101 | while (idt < enddt && times[idt].date() == d->mExDates[i]) { | 1101 | while (idt < enddt && times[idt].date() == d->mExDates[i]) { | ||
1102 | times.removeAt(idt); | 1102 | times.removeAt(idt); | ||
1103 | --enddt; | 1103 | --enddt; | ||
1104 | } | 1104 | } | ||
1105 | } | 1105 | } | ||
1106 | SortableList<QDateTime> extimes; | 1106 | QList<QDateTime> extimes; | ||
1107 | for (i = 0, count = d->mExRules.count(); i < count; ++i) { | 1107 | for (i = 0, count = d->mExRules.count(); i < count; ++i) { | ||
1108 | extimes += d->mExRules[i]->timesInInterval(start, end); | 1108 | extimes += d->mExRules[i]->timesInInterval(start, end); | ||
1109 | } | 1109 | } | ||
1110 | extimes += d->mExDateTimes; | 1110 | extimes += d->mExDateTimes; | ||
1111 | sortAndRemoveDuplicates(extimes); | 1111 | sortAndRemoveDuplicates(extimes); | ||
1112 | inplaceSetDifference(times, extimes); | 1112 | inplaceSetDifference(times, extimes); | ||
1113 | return times; | 1113 | return times; | ||
1114 | } | 1114 | } | ||
Show All 15 Lines | 1125 | while (loop < 1000) { | |||
1130 | // 1.2) Add the next recurrence for each of the RRULEs | 1130 | // 1.2) Add the next recurrence for each of the RRULEs | ||
1131 | // 2) Take the earliest recurrence of these = QDateTime nextDT | 1131 | // 2) Take the earliest recurrence of these = QDateTime nextDT | ||
1132 | // 3) If that date/time is not excluded, either explicitly by an EXDATE or | 1132 | // 3) If that date/time is not excluded, either explicitly by an EXDATE or | ||
1133 | // by an EXRULE, return nextDT as the next date/time of the recurrence | 1133 | // by an EXRULE, return nextDT as the next date/time of the recurrence | ||
1134 | // 4) If it's excluded, start all at 1), but starting at nextDT (instead | 1134 | // 4) If it's excluded, start all at 1), but starting at nextDT (instead | ||
1135 | // of preDateTime). Loop at most 1000 times. | 1135 | // of preDateTime). Loop at most 1000 times. | ||
1136 | ++loop; | 1136 | ++loop; | ||
1137 | // First, get the next recurrence from the RDate lists | 1137 | // First, get the next recurrence from the RDate lists | ||
1138 | SortableList<QDateTime> dates; | 1138 | QList<QDateTime> dates; | ||
1139 | if (nextDT < startDateTime()) { | 1139 | if (nextDT < startDateTime()) { | ||
1140 | dates << startDateTime(); | 1140 | dates << startDateTime(); | ||
1141 | } | 1141 | } | ||
1142 | 1142 | | |||
1143 | // Assume that the rdatetime list is sorted | 1143 | // Assume that the rdatetime list is sorted | ||
1144 | const auto it = std::upper_bound(d->mRDateTimes.constBegin(), d->mRDateTimes.constEnd(), nextDT); | 1144 | const auto it = std::upper_bound(d->mRDateTimes.constBegin(), d->mRDateTimes.constEnd(), nextDT); | ||
1145 | if (it != d->mRDateTimes.constEnd()) { | 1145 | if (it != d->mRDateTimes.constEnd()) { | ||
1146 | dates << *it; | 1146 | dates << *it; | ||
▲ Show 20 Lines • Show All 54 Lines • ▼ Show 20 Line(s) | 1197 | while (loop < 1000) { | |||
1201 | // 1.2) Add the next recurrence for each of the RRULEs | 1201 | // 1.2) Add the next recurrence for each of the RRULEs | ||
1202 | // 2) Take the earliest recurrence of these = QDateTime nextDT | 1202 | // 2) Take the earliest recurrence of these = QDateTime nextDT | ||
1203 | // 3) If that date/time is not excluded, either explicitly by an EXDATE or | 1203 | // 3) If that date/time is not excluded, either explicitly by an EXDATE or | ||
1204 | // by an EXRULE, return nextDT as the next date/time of the recurrence | 1204 | // by an EXRULE, return nextDT as the next date/time of the recurrence | ||
1205 | // 4) If it's excluded, start all at 1), but starting at nextDT (instead | 1205 | // 4) If it's excluded, start all at 1), but starting at nextDT (instead | ||
1206 | // of preDateTime). Loop at most 1000 times. | 1206 | // of preDateTime). Loop at most 1000 times. | ||
1207 | ++loop; | 1207 | ++loop; | ||
1208 | // First, get the next recurrence from the RDate lists | 1208 | // First, get the next recurrence from the RDate lists | ||
1209 | SortableList<QDateTime> dates; | 1209 | QList<QDateTime> dates; | ||
1210 | if (prevDT > startDateTime()) { | 1210 | if (prevDT > startDateTime()) { | ||
1211 | dates << startDateTime(); | 1211 | dates << startDateTime(); | ||
1212 | } | 1212 | } | ||
1213 | 1213 | | |||
1214 | const auto it = strictLowerBound(d->mRDateTimes.constBegin(), d->mRDateTimes.constEnd(), prevDT); | 1214 | const auto it = strictLowerBound(d->mRDateTimes.constBegin(), d->mRDateTimes.constEnd(), prevDT); | ||
1215 | if (it != d->mRDateTimes.constEnd()) { | 1215 | if (it != d->mRDateTimes.constEnd()) { | ||
1216 | dates << *it; | 1216 | dates << *it; | ||
1217 | } | 1217 | } | ||
▲ Show 20 Lines • Show All 114 Lines • ▼ Show 20 Line(s) | 1331 | if (d->mRecurReadOnly) { | |||
1332 | return; | 1332 | return; | ||
1333 | } | 1333 | } | ||
1334 | 1334 | | |||
1335 | d->mExRules.removeAll(exrule); | 1335 | d->mExRules.removeAll(exrule); | ||
1336 | delete exrule; | 1336 | delete exrule; | ||
1337 | updated(); | 1337 | updated(); | ||
1338 | } | 1338 | } | ||
1339 | 1339 | | |||
1340 | SortableList<QDateTime> Recurrence::rDateTimes() const | 1340 | QList<QDateTime> Recurrence::rDateTimes() const | ||
1341 | { | 1341 | { | ||
1342 | return d->mRDateTimes; | 1342 | return d->mRDateTimes; | ||
1343 | } | 1343 | } | ||
1344 | 1344 | | |||
1345 | void Recurrence::setRDateTimes(const SortableList<QDateTime> &rdates) | 1345 | void Recurrence::setRDateTimes(const QList<QDateTime> &rdates) | ||
1346 | { | 1346 | { | ||
1347 | if (d->mRecurReadOnly) { | 1347 | if (d->mRecurReadOnly) { | ||
1348 | return; | 1348 | return; | ||
1349 | } | 1349 | } | ||
1350 | 1350 | | |||
1351 | d->mRDateTimes = rdates; | 1351 | d->mRDateTimes = rdates; | ||
1352 | sortAndRemoveDuplicates(d->mRDateTimes); | 1352 | sortAndRemoveDuplicates(d->mRDateTimes); | ||
1353 | updated(); | 1353 | updated(); | ||
Show All 30 Lines | 1383 | { | |||
1384 | if (d->mRecurReadOnly) { | 1384 | if (d->mRecurReadOnly) { | ||
1385 | return; | 1385 | return; | ||
1386 | } | 1386 | } | ||
1387 | 1387 | | |||
1388 | setInsert(d->mRDates, rdate); | 1388 | setInsert(d->mRDates, rdate); | ||
1389 | updated(); | 1389 | updated(); | ||
1390 | } | 1390 | } | ||
1391 | 1391 | | |||
1392 | SortableList<QDateTime> Recurrence::exDateTimes() const | 1392 | QList<QDateTime> Recurrence::exDateTimes() const | ||
1393 | { | 1393 | { | ||
1394 | return d->mExDateTimes; | 1394 | return d->mExDateTimes; | ||
1395 | } | 1395 | } | ||
1396 | 1396 | | |||
1397 | void Recurrence::setExDateTimes(const SortableList<QDateTime> &exdates) | 1397 | void Recurrence::setExDateTimes(const QList<QDateTime> &exdates) | ||
1398 | { | 1398 | { | ||
1399 | if (d->mRecurReadOnly) { | 1399 | if (d->mRecurReadOnly) { | ||
1400 | return; | 1400 | return; | ||
1401 | } | 1401 | } | ||
1402 | 1402 | | |||
1403 | d->mExDateTimes = exdates; | 1403 | d->mExDateTimes = exdates; | ||
1404 | sortAndRemoveDuplicates(d->mExDateTimes); | 1404 | sortAndRemoveDuplicates(d->mExDateTimes); | ||
1405 | } | 1405 | } | ||
▲ Show 20 Lines • Show All 88 Lines • ▼ Show 20 Line(s) | |||||
1494 | } | 1494 | } | ||
1495 | 1495 | | |||
1496 | KCALCORE_EXPORT QDataStream &KCalCore::operator<<(QDataStream &out, KCalCore::Recurrence *r) | 1496 | KCALCORE_EXPORT QDataStream &KCalCore::operator<<(QDataStream &out, KCalCore::Recurrence *r) | ||
1497 | { | 1497 | { | ||
1498 | if (!r) { | 1498 | if (!r) { | ||
1499 | return out; | 1499 | return out; | ||
1500 | } | 1500 | } | ||
1501 | 1501 | | |||
1502 | serializeQDateTimeSortableList(out, r->d->mRDateTimes); | 1502 | serializeQDateTimeList(out, r->d->mRDateTimes); | ||
1503 | serializeQDateTimeSortableList(out, r->d->mExDateTimes); | 1503 | serializeQDateTimeList(out, r->d->mExDateTimes); | ||
1504 | out << r->d->mRDates; | 1504 | out << r->d->mRDates; | ||
1505 | serializeQDateTimeAsKDateTime(out, r->d->mStartDateTime); | 1505 | serializeQDateTimeAsKDateTime(out, r->d->mStartDateTime); | ||
1506 | out << r->d->mCachedType | 1506 | out << r->d->mCachedType | ||
1507 | << r->d->mAllDay << r->d->mRecurReadOnly << r->d->mExDates | 1507 | << r->d->mAllDay << r->d->mRecurReadOnly << r->d->mExDates | ||
1508 | << r->d->mExRules.count() << r->d->mRRules.count(); | 1508 | << r->d->mExRules.count() << r->d->mRRules.count(); | ||
1509 | 1509 | | |||
1510 | for (RecurrenceRule *rule : qAsConst(r->d->mExRules)) { | 1510 | for (RecurrenceRule *rule : qAsConst(r->d->mExRules)) { | ||
1511 | out << rule; | 1511 | out << rule; | ||
Show All 9 Lines | |||||
1521 | KCALCORE_EXPORT QDataStream &KCalCore::operator>>(QDataStream &in, KCalCore::Recurrence *r) | 1521 | KCALCORE_EXPORT QDataStream &KCalCore::operator>>(QDataStream &in, KCalCore::Recurrence *r) | ||
1522 | { | 1522 | { | ||
1523 | if (!r) { | 1523 | if (!r) { | ||
1524 | return in; | 1524 | return in; | ||
1525 | } | 1525 | } | ||
1526 | 1526 | | |||
1527 | int rruleCount, exruleCount; | 1527 | int rruleCount, exruleCount; | ||
1528 | 1528 | | |||
1529 | deserializeQDateTimeSortableList(in, r->d->mRDateTimes); | 1529 | deserializeQDateTimeList(in, r->d->mRDateTimes); | ||
1530 | deserializeQDateTimeSortableList(in, r->d->mExDateTimes); | 1530 | deserializeQDateTimeList(in, r->d->mExDateTimes); | ||
1531 | in >> r->d->mRDates; | 1531 | in >> r->d->mRDates; | ||
1532 | deserializeKDateTimeAsQDateTime(in, r->d->mStartDateTime); | 1532 | deserializeKDateTimeAsQDateTime(in, r->d->mStartDateTime); | ||
1533 | in >> r->d->mCachedType | 1533 | in >> r->d->mCachedType | ||
1534 | >> r->d->mAllDay >> r->d->mRecurReadOnly >> r->d->mExDates | 1534 | >> r->d->mAllDay >> r->d->mRecurReadOnly >> r->d->mExDates | ||
1535 | >> exruleCount >> rruleCount; | 1535 | >> exruleCount >> rruleCount; | ||
1536 | 1536 | | |||
1537 | r->d->mExRules.clear(); | 1537 | r->d->mExRules.clear(); | ||
1538 | r->d->mRRules.clear(); | 1538 | r->d->mRRules.clear(); | ||
Show All 17 Lines |