diff --git a/src/calendarevent.h b/src/calendarevent.h index 9d6914df..1bc77d43 100644 --- a/src/calendarevent.h +++ b/src/calendarevent.h @@ -43,7 +43,6 @@ class CalendarManager; class CalendarEvent : public QObject { Q_OBJECT - Q_ENUMS(Recur) Q_ENUMS(Reminder) Q_ENUMS(TimeSpec) Q_ENUMS(Secrecy) @@ -76,9 +75,11 @@ class CalendarEvent : public QObject RecurWeekly, RecurBiweekly, RecurMonthly, + RecurMonthlyByDayOfWeek, RecurYearly, RecurCustom }; + Q_ENUM(Recur) enum TimeSpec { SpecLocalZone, diff --git a/src/calendarutils.cpp b/src/calendarutils.cpp index 4dc2dff7..7ff39e1d 100644 --- a/src/calendarutils.cpp +++ b/src/calendarutils.cpp @@ -70,6 +70,14 @@ CalendarEvent::Recur CalendarUtils::convertRecurrence(const KCalCore::Event::Ptr return CalendarEvent::RecurBiweekly; } else if (rt == KCalCore::Recurrence::rMonthlyDay && freq == 1) { return CalendarEvent::RecurMonthly; + } else if (rt == KCalCore::Recurrence::rMonthlyPos && freq == 1) { + const QList monthPositions = event->recurrence()->monthPositions(); + if (monthPositions.length() == 1 + && monthPositions.first().day() == event->dtStart().date().dayOfWeek()) { + return CalendarEvent::RecurMonthlyByDayOfWeek; + } else { + return CalendarEvent::RecurCustom; + } } else if (rt == KCalCore::Recurrence::rYearlyMonth && freq == 1) { return CalendarEvent::RecurYearly; } diff --git a/src/calendarworker.cpp b/src/calendarworker.cpp index 42658aea..c04053bf 100644 --- a/src/calendarworker.cpp +++ b/src/calendarworker.cpp @@ -345,7 +345,7 @@ bool CalendarWorker::setRecurrence(KCalCore::Event::Ptr &event, CalendarEvent::R if (recur == CalendarEvent::RecurOnce) event->recurrence()->clear(); - if (oldRecur != recur) { + if (oldRecur != recur || recur == CalendarEvent::RecurMonthlyByDayOfWeek) { switch (recur) { case CalendarEvent::RecurOnce: break; @@ -361,6 +361,16 @@ bool CalendarWorker::setRecurrence(KCalCore::Event::Ptr &event, CalendarEvent::R case CalendarEvent::RecurMonthly: event->recurrence()->setMonthly(1); break; + case CalendarEvent::RecurMonthlyByDayOfWeek: { + event->recurrence()->setMonthly(1); + const QDate at(event->dtStart().date()); + if (at.addDays(7).month() == at.month()) { + event->recurrence()->addMonthlyPos((at.day() - 1) / 7 + 1, at.dayOfWeek()); + } else { + event->recurrence()->addMonthlyPos(-1, at.dayOfWeek()); + } + break; + } case CalendarEvent::RecurYearly: event->recurrence()->setYearly(1); break; diff --git a/tests/tst_calendarevent/tst_calendarevent.cpp b/tests/tst_calendarevent/tst_calendarevent.cpp index d5f91cd1..63807fa3 100644 --- a/tests/tst_calendarevent/tst_calendarevent.cpp +++ b/tests/tst_calendarevent/tst_calendarevent.cpp @@ -27,6 +27,8 @@ private slots: void testRecurrenceException(); void testDate_data(); void testDate(); + void testRecurrence_data(); + void testRecurrence(); private: bool saveEvent(CalendarEventModification *eventMod, QString *uid); @@ -423,6 +425,57 @@ void tst_CalendarEvent::testDate() mSavedEvents.insert(uid); } +void tst_CalendarEvent::testRecurrence_data() +{ + QTest::addColumn("recurType"); + QTest::newRow("No recurrence") << CalendarEvent::RecurOnce; + QTest::newRow("Every day") << CalendarEvent::RecurDaily; + QTest::newRow("Every week") << CalendarEvent::RecurWeekly; + QTest::newRow("Every two weeks") << CalendarEvent::RecurBiweekly; + QTest::newRow("Every month") << CalendarEvent::RecurMonthly; + QTest::newRow("Every month on same day of week") << CalendarEvent::RecurMonthlyByDayOfWeek; + QTest::newRow("Every year") << CalendarEvent::RecurYearly; +} + +void tst_CalendarEvent::testRecurrence() +{ + QFETCH(CalendarEvent::Recur, recurType); + + CalendarEventModification *eventMod = calendarApi->createNewEvent(); + QVERIFY(eventMod != 0); + + const QDateTime dt(QDate(2020, 4, 27), QTime(8, 0)); + eventMod->setStartTime(dt, CalendarEvent::SpecLocalZone); + eventMod->setEndTime(dt.addSecs(10*60), CalendarEvent::SpecLocalZone); + eventMod->setRecur(recurType); + eventMod->setDescription(QMetaEnum::fromType().valueToKey(recurType)); + + QString uid; + bool ok = saveEvent(eventMod, &uid); + if (!ok) { + QFAIL("Failed to fetch new event uid"); + } + QVERIFY(!uid.isEmpty()); + mSavedEvents.insert(uid); + + CalendarEventQuery query; + query.setUniqueId(uid); + + for (int i = 0; i < 30; i++) { + if (query.event()) + break; + + QTest::qWait(100); + } + CalendarEvent *event = (CalendarEvent*)query.event(); + QVERIFY(event); + + QCOMPARE(event->recur(), recurType); + + calendarApi->removeAll(uid); + mSavedEvents.remove(uid); +} + void tst_CalendarEvent::cleanupTestCase() { foreach (const QString &uid, mSavedEvents) {