Commit 0a8f6a6d authored by Daniel Vrátil's avatar Daniel Vrátil 🤖
Browse files

Move the KCalCore porting utils to KAlarmCal

KAlarmCal and KAlarm are the only last two components depending heavily
on KDateTime. The helper utilities from KCalCore help to bridge them
with the QDateTime world.
parent 7fb2492c
......@@ -15,6 +15,7 @@ set(kalarmcal_LIB_SRCS
collectionattribute.cpp
compatibilityattribute.cpp
eventattribute.cpp
utils.cpp
)
ecm_qt_declare_logging_category(kalarmcal_LIB_SRCS HEADER kalarmcal_debug.h IDENTIFIER KALARMCAL_LOG CATEGORY_NAME org.kde.pim.kalarmcal)
......@@ -60,6 +61,7 @@ ecm_generate_headers(KAlarmCal_CamelCase_HEADERS
KAEvent
KARecurrence
Repetition
Utils
PREFIX KAlarmCal
REQUIRED_HEADERS KAlarmCal_HEADERS
)
......
......@@ -25,6 +25,8 @@
#include "alarmtext.h"
#include "identities.h"
#include "version.h"
#include "utils.h"
#include <kholidays/holidayregion.h>
#include <kcalcore/memorycalendar.h>
#include <kholidays/holiday.h>
......@@ -33,7 +35,6 @@ using namespace KHolidays;
#include <ksystemtimezone.h>
#include <klocalizedstring.h>
#include <kglobal.h>
#include <kcalcore/utils.h>
#include "kalarmcal_debug.h"
......@@ -196,11 +197,11 @@ public:
DateTime mainDateTime(bool withRepeats = false) const
{
return (withRepeats && mNextRepeat && mRepetition)
? KCalCore::q2k(mRepetition.duration(mNextRepeat).end(KCalCore::k2q(mNextMainDateTime.kDateTime()))) : mNextMainDateTime;
? q2k(mRepetition.duration(mNextRepeat).end(k2q(mNextMainDateTime.kDateTime()))) : mNextMainDateTime;
}
DateTime mainEndRepeatTime() const
{
return mRepetition ? KCalCore::q2k(mRepetition.duration().end(KCalCore::k2q(mNextMainDateTime.kDateTime()))) : mNextMainDateTime;
return mRepetition ? q2k(mRepetition.duration().end(k2q(mNextMainDateTime.kDateTime()))) : mNextMainDateTime;
}
DateTime deferralLimit(KAEvent::DeferLimitType * = nullptr) const;
KAEvent::Flags flags() const;
......@@ -855,7 +856,7 @@ void KAEventPrivate::set(const Event::Ptr &event)
}
}
mNextMainDateTime = readDateTime(event, dateOnly, mStartDateTime);
mCreatedDateTime = KCalCore::q2k(event->created());
mCreatedDateTime = q2k(event->created());
if (dateOnly && !mRepetition.isDaily()) {
mRepetition.set(Duration(mRepetition.intervalDays(), Duration::Days));
}
......@@ -902,7 +903,7 @@ void KAEventPrivate::set(const Event::Ptr &event)
Duration deferralOffset;
for (AlarmMap::ConstIterator it = alarmMap.constBegin(); it != alarmMap.constEnd(); ++it) {
const AlarmData &data = it.value();
const DateTime dateTime = data.alarm->hasStartOffset() ? KCalCore::q2k(data.alarm->startOffset().end(KCalCore::k2q(mNextMainDateTime.effectiveKDateTime()))) : KCalCore::q2k(data.alarm->time());
const DateTime dateTime = data.alarm->hasStartOffset() ? q2k(data.alarm->startOffset().end(k2q(mNextMainDateTime.effectiveKDateTime()))) : q2k(data.alarm->time());
switch (data.type) {
case MAIN_ALARM:
mMainExpired = false;
......@@ -949,7 +950,7 @@ void KAEventPrivate::set(const Event::Ptr &event)
mDeferral = (data.type == DEFERRED_REMINDER_ALARM) ? REMINDER_DEFERRAL : NORMAL_DEFERRAL;
if (data.timedDeferral) {
// Don't use start-of-day time for applying timed deferral alarm offset
mDeferralTime = data.alarm->hasStartOffset() ? KCalCore::q2k(data.alarm->startOffset().end(KCalCore::k2q(mNextMainDateTime.calendarKDateTime()))) : KCalCore::q2k(data.alarm->time());
mDeferralTime = data.alarm->hasStartOffset() ? q2k(data.alarm->startOffset().end(k2q(mNextMainDateTime.calendarKDateTime()))) : q2k(data.alarm->time());
} else {
mDeferralTime = dateTime;
mDeferralTime.setDateOnly(true);
......@@ -1091,10 +1092,10 @@ void KAEventPrivate::set(const Event::Ptr &event)
DateTime dt = mRecurrence->getNextDateTime(mStartDateTime.addDays(-1).kDateTime());
dt.setDateOnly(mStartDateTime.isDateOnly());
if (mDeferralTime.isDateOnly()) {
mDeferralTime = KCalCore::q2k(deferralOffset.end(KCalCore::k2q(dt.kDateTime())));
mDeferralTime = q2k(deferralOffset.end(k2q(dt.kDateTime())));
mDeferralTime.setDateOnly(true);
} else {
mDeferralTime = KCalCore::q2k(deferralOffset.end(KCalCore::k2q(dt.effectiveKDateTime())));
mDeferralTime = q2k(deferralOffset.end(k2q(dt.effectiveKDateTime())));
}
}
if (mDeferral != NO_DEFERRAL) {
......@@ -1330,7 +1331,7 @@ bool KAEventPrivate::updateKCalEvent(const Event::Ptr &ev, KAEvent::UidAction ui
* UTC DATE-TIME value. So always use a time relative to DTSTART instead of
* an absolute time.
*/
ev->setDtStart(KCalCore::k2q(mStartDateTime.calendarKDateTime()));
ev->setDtStart(k2q(mStartDateTime.calendarKDateTime()));
ev->setAllDay(false);
ev->setDtEnd(QDateTime());
......@@ -1484,7 +1485,7 @@ bool KAEventPrivate::updateKCalEvent(const Event::Ptr &ev, KAEvent::UidAction ui
ev->clearRecurrence();
}
if (mCreatedDateTime.isValid()) {
ev->setCreated(KCalCore::k2q(mCreatedDateTime));
ev->setCreated(k2q(mCreatedDateTime));
}
ev->setReadOnly(readOnly);
ev->endUpdates(); // finally issue an update notification
......@@ -3150,7 +3151,7 @@ bool KAEventPrivate::occursAfter(const KDateTime &preDateTime, bool includeRepet
}
if (includeRepetitions && mRepetition) {
if (preDateTime < KCalCore::q2k(mRepetition.duration().end(KCalCore::k2q(dt)))) {
if (preDateTime < q2k(mRepetition.duration().end(k2q(dt)))) {
return true;
}
}
......@@ -3180,7 +3181,7 @@ KAEvent::OccurType KAEventPrivate::setNextOccurrence(const KDateTime &preDateTim
// we find the earliest recurrence which has a repetition falling after
// the specified preDateTime.
if (mRepetition) {
pre = KCalCore::q2k(mRepetition.duration(-mRepetition.count()).end(KCalCore::k2q(preDateTime)));
pre = q2k(mRepetition.duration(-mRepetition.count()).end(k2q(preDateTime)));
}
DateTime afterPre; // next recurrence after 'pre'
......@@ -3249,7 +3250,7 @@ KAEvent::OccurType KAEventPrivate::nextOccurrence(const KDateTime &preDateTime,
if (!mRepetition) {
includeRepetitions = KAEvent::IGNORE_REPETITION;
} else {
pre = KCalCore::q2k(mRepetition.duration(-mRepetition.count()).end(KCalCore::k2q(preDateTime)));
pre = q2k(mRepetition.duration(-mRepetition.count()).end(k2q(preDateTime)));
}
}
......@@ -3269,7 +3270,7 @@ KAEvent::OccurType KAEventPrivate::nextOccurrence(const KDateTime &preDateTime,
// RETURN_REPETITION or ALLOW_FOR_REPETITION
// The next occurrence is a sub-repetition
int repetition = mRepetition.nextRepeatCount(result.kDateTime(), preDateTime);
const DateTime repeatDT = KCalCore::q2k(mRepetition.duration(repetition).end(KCalCore::k2q(result.kDateTime())));
const DateTime repeatDT = q2k(mRepetition.duration(repetition).end(k2q(result.kDateTime())));
if (recurs) {
// We've found a recurrence before the specified date/time, which has
// a sub-repetition after the date/time.
......@@ -3283,7 +3284,7 @@ KAEvent::OccurType KAEventPrivate::nextOccurrence(const KDateTime &preDateTime,
if (includeRepetitions == KAEvent::RETURN_REPETITION && result <= preDateTime) {
// The next occurrence is a sub-repetition
repetition = mRepetition.nextRepeatCount(result.kDateTime(), preDateTime);
result = KCalCore::q2k(mRepetition.duration(repetition).end(KCalCore::k2q(result.kDateTime())));
result = q2k(mRepetition.duration(repetition).end(k2q(result.kDateTime())));
type = static_cast<KAEvent::OccurType>(type | KAEvent::OCCURRENCE_REPEAT);
}
return type;
......@@ -3349,7 +3350,7 @@ KAEvent::OccurType KAEventPrivate::previousOccurrence(const KDateTime &afterDate
// Find the latest repetition which is before the specified time.
const int repetition = mRepetition.previousRepeatCount(result.effectiveKDateTime(), afterDateTime);
if (repetition > 0) {
result = KCalCore::q2k(mRepetition.duration(qMin(repetition, mRepetition.count())).end(KCalCore::k2q(result.kDateTime())));
result = q2k(mRepetition.duration(qMin(repetition, mRepetition.count())).end(k2q(result.kDateTime())));
return static_cast<KAEvent::OccurType>(type | KAEvent::OCCURRENCE_REPEAT);
}
}
......@@ -3840,7 +3841,7 @@ void KAEventPrivate::dumpDebug() const
*/
DateTime KAEventPrivate::readDateTime(const Event::Ptr &event, bool dateOnly, DateTime &start)
{
start = KCalCore::q2k(event->dtStart());
start = q2k(event->dtStart());
if (dateOnly) {
// A date-only event is indicated by the X-KDE-KALARM-FLAGS:DATE property, not
// by a date-only start date/time (for the reasons given in updateKCalEvent()).
......@@ -5052,12 +5053,12 @@ bool KAEvent::convertKCalEvents(const Calendar::Ptr &calendar, int calendarVersi
if (adjustSummerTime) {
// The calendar file was written by the KDE 3.0.0 version of KAlarm 0.5.7.
// Summer time was ignored when converting to UTC.
KDateTime dt = KCalCore::q2k(alarm->time());
KDateTime dt = q2k(alarm->time());
const time_t t = dt.toTime_t();
const struct tm *dtm = localtime(&t);
if (dtm->tm_isdst) {
dt = dt.addSecs(-3600);
alarm->setTime(KCalCore::k2q(dt));
alarm->setTime(k2q(dt));
}
}
}
......@@ -5244,7 +5245,7 @@ bool KAEvent::convertKCalEvents(const Calendar::Ptr &calendar, int calendarVersi
*/
const QStringList flags = event->customProperty(KACalendar::APPNAME, KAEventPrivate::FLAGS_PROPERTY).split(KAEventPrivate::SC, QString::SkipEmptyParts);
const bool dateOnly = flags.contains(KAEventPrivate::DATE_ONLY_FLAG);
KDateTime startDateTime = KCalCore::q2k(event->dtStart(), dateOnly);
KDateTime startDateTime = q2k(event->dtStart(), dateOnly);
if (dateOnly) {
startDateTime.setDateOnly(true);
}
......@@ -5282,7 +5283,7 @@ bool KAEvent::convertKCalEvents(const Calendar::Ptr &calendar, int calendarVersi
// All main alarms are supposed to be at the same time, so
// don't readjust the event's time for subsequent main alarms.
mainExpired = false;
nextMainDateTime = KCalCore::q2k(alarm->time());
nextMainDateTime = q2k(alarm->time());
nextMainDateTime.setDateOnly(dateOnly);
nextMainDateTime = nextMainDateTime.toTimeSpec(startDateTime);
if (nextMainDateTime != startDateTime) {
......@@ -5300,7 +5301,7 @@ bool KAEvent::convertKCalEvents(const Calendar::Ptr &calendar, int calendarVersi
// It's an expired recurrence.
// Set the alarm offset relative to the first actual occurrence
// (taking account of possible exceptions).
KDateTime dt = KCalCore::q2k(event->recurrence()->getNextDateTime(KCalCore::k2q(startDateTime).addDays(-1)));
KDateTime dt = q2k(event->recurrence()->getNextDateTime(k2q(startDateTime).addDays(-1)));
dt.setDateOnly(dateOnly);
adjustment = startDateTime.secsTo(dt);
} else {
......@@ -5488,10 +5489,10 @@ bool KAEventPrivate::convertStartOfDay(const Event::Ptr &event)
const QStringList flags = event->customProperty(KACalendar::APPNAME, KAEventPrivate::FLAGS_PROPERTY).split(KAEventPrivate::SC, QString::SkipEmptyParts);
if (flags.indexOf(KAEventPrivate::DATE_ONLY_FLAG) >= 0) {
// It's an untimed event, so fix it
const KDateTime oldDt = KCalCore::q2k(event->dtStart());
const KDateTime oldDt = q2k(event->dtStart());
const int adjustment = oldDt.time().secsTo(midnight);
if (adjustment) {
event->setDtStart(QDateTime(oldDt.date(), midnight, KCalCore::specToZone(oldDt.timeSpec())));
event->setDtStart(QDateTime(oldDt.date(), midnight, specToZone(oldDt.timeSpec())));
int deferralOffset = 0;
AlarmMap alarmMap;
readAlarms(event, &alarmMap);
......@@ -5528,7 +5529,7 @@ bool KAEventPrivate::convertStartOfDay(const Event::Ptr &event)
}
if ((data.type & DEFERRED_ALARM) && !data.timedDeferral) {
// Found a date-only deferral alarm, so adjust its time
QDateTime altime = data.alarm->startOffset().end(KCalCore::k2q(nextMainDateTime));
QDateTime altime = data.alarm->startOffset().end(k2q(nextMainDateTime));
altime.setTime(midnight);
deferralOffset = data.alarm->startOffset().asSeconds();
newDeferralOffset = event->dtStart().secsTo(altime);
......@@ -5650,7 +5651,7 @@ KAAlarm::Type KAAlarm::type() const
DateTime KAAlarm::dateTime(bool withRepeats) const
{
return (withRepeats && d->mNextRepeat && d->mRepetition)
? KCalCore::q2k(d->mRepetition.duration(d->mNextRepeat).end(KCalCore::k2q(d->mNextMainDateTime.kDateTime())))
? q2k(d->mRepetition.duration(d->mNextRepeat).end(k2q(d->mNextMainDateTime.kDateTime())))
: d->mNextMainDateTime;
}
......
......@@ -21,10 +21,10 @@
*/
#include "karecurrence.h"
#include "utils.h"
#include <kcalcore/recurrence.h>
#include <kcalcore/icalformat.h>
#include <kcalcore/utils.h>
#include <klocalizedstring.h>
#include "kalarmcal_debug.h"
......@@ -238,7 +238,7 @@ bool KARecurrence::Private::init(RecurrenceRule::PeriodType recurType, int freq,
} else if (dateOnly) {
mRecurrence.setEndDate(end.date());
} else {
mRecurrence.setEndDateTime(KCalCore::k2q(end));
mRecurrence.setEndDateTime(k2q(end));
}
KDateTime startdt = start;
if (recurType == RecurrenceRule::rYearly
......@@ -258,7 +258,7 @@ bool KARecurrence::Private::init(RecurrenceRule::PeriodType recurType, int freq,
}
mFeb29Type = feb29Type;
}
mRecurrence.setStartDateTime(KCalCore::k2q(startdt), dateOnly); // sets recurrence all-day if date-only
mRecurrence.setStartDateTime(k2q(startdt), dateOnly); // sets recurrence all-day if date-only
return true;
}
......@@ -485,7 +485,7 @@ void KARecurrence::Private::writeRecurrence(const KARecurrence *q, Recurrence &r
if (count) {
recur.setDuration(count);
} else {
recur.setEndDateTime(KCalCore::k2q(endDateTime()));
recur.setEndDateTime(k2q(endDateTime()));
}
switch (q->type()) {
case DAILY:
......@@ -525,7 +525,7 @@ void KARecurrence::Private::writeRecurrence(const KARecurrence *q, Recurrence &r
rrule2->setStartDt(mRecurrence.startDateTime());
rrule2->setAllDay(mRecurrence.allDay());
if (!count) {
rrule2->setEndDt(KCalCore::k2q(endDateTime()));
rrule2->setEndDt(k2q(endDateTime()));
}
if (mFeb29Type == Feb29_Mar1) {
QList<int> ds;
......@@ -564,14 +564,14 @@ void KARecurrence::Private::writeRecurrence(const KARecurrence *q, Recurrence &r
* is not lost should the user later change the recurrence count.
*/
const KDateTime end = endDateTime();
const int count1 = rrule1->durationTo(KCalCore::k2q(end))
const int count1 = rrule1->durationTo(k2q(end))
- (rrule1->recursOn(mRecurrence.startDate(), mRecurrence.startDateTime().timeZone()) ? 0 : 1);
if (count1 > 0) {
rrule1->setDuration(count1);
} else {
rrule1->setEndDt(mRecurrence.startDateTime());
}
const int count2 = rrule2->durationTo(KCalCore::k2q(end))
const int count2 = rrule2->durationTo(k2q(end))
- (rrule2->recursOn(mRecurrence.startDate(), mRecurrence.startDateTime().timeZone()) ? 0 : 1);
if (count2 > 0) {
rrule2->setDuration(count2);
......@@ -591,7 +591,7 @@ void KARecurrence::Private::writeRecurrence(const KARecurrence *q, Recurrence &r
KDateTime KARecurrence::startDateTime() const
{
return KCalCore::q2k(d->mRecurrence.startDateTime());
return q2k(d->mRecurrence.startDateTime());
}
QDate KARecurrence::startDate() const
......@@ -601,7 +601,7 @@ QDate KARecurrence::startDate() const
void KARecurrence::setStartDateTime(const KDateTime &dt, bool dateOnly)
{
d->mRecurrence.setStartDateTime(KCalCore::k2q(dt), dateOnly);
d->mRecurrence.setStartDateTime(k2q(dt), dateOnly);
if (dateOnly) {
d->mRecurrence.setAllDay(true);
}
......@@ -623,7 +623,7 @@ KDateTime KARecurrence::Private::endDateTime() const
* (count = 0), or it ends on the start date (count = 1).
* So just use the normal KCal end date calculation.
*/
return KCalCore::q2k(mRecurrence.endDateTime());
return q2k(mRecurrence.endDateTime());
}
/* Create a temporary recurrence rule to find the end date.
......@@ -633,7 +633,7 @@ KDateTime KARecurrence::Private::endDateTime() const
*/
RecurrenceRule *rrule = new RecurrenceRule();
rrule->setRecurrenceType(RecurrenceRule::rYearly);
KDateTime dt = KCalCore::q2k(mRecurrence.startDateTime());
KDateTime dt = q2k(mRecurrence.startDateTime());
QDate da = dt.date();
switch (da.day()) {
case 29:
......@@ -658,7 +658,7 @@ KDateTime KARecurrence::Private::endDateTime() const
break;
}
dt.setDate(da);
rrule->setStartDt(KCalCore::k2q(dt));
rrule->setStartDt(k2q(dt));
rrule->setAllDay(mRecurrence.allDay());
rrule->setFrequency(mRecurrence.frequency());
rrule->setDuration(mRecurrence.duration());
......@@ -666,7 +666,7 @@ KDateTime KARecurrence::Private::endDateTime() const
ds.append(28);
rrule->setByMonthDays(ds);
rrule->setByMonths(mRecurrence.defaultRRuleConst()->byMonths());
dt = KCalCore::q2k(rrule->endDt());
dt = q2k(rrule->endDt());
delete rrule;
// We've found the end date for a recurrence on the 28th. Unless that date
......@@ -693,7 +693,7 @@ void KARecurrence::setEndDate(const QDate &endDate)
void KARecurrence::setEndDateTime(const KDateTime &endDateTime)
{
d->mRecurrence.setEndDateTime(KCalCore::k2q(endDateTime));
d->mRecurrence.setEndDateTime(k2q(endDateTime));
}
bool KARecurrence::allDay() const
......@@ -801,10 +801,10 @@ KDateTime KARecurrence::getNextDateTime(const KDateTime &preDateTime) const
case ANNUAL_POS: {
Recurrence recur;
writeRecurrence(recur);
return KCalCore::q2k(recur.getNextDateTime(KCalCore::k2q(preDateTime)));
return q2k(recur.getNextDateTime(k2q(preDateTime)));
}
default:
return KCalCore::q2k(d->mRecurrence.getNextDateTime(KCalCore::k2q(preDateTime)));
return q2k(d->mRecurrence.getNextDateTime(k2q(preDateTime)));
}
}
......@@ -818,10 +818,10 @@ KDateTime KARecurrence::getPreviousDateTime(const KDateTime &afterDateTime) cons
case ANNUAL_POS: {
Recurrence recur;
writeRecurrence(recur);
return KCalCore::q2k(recur.getPreviousDateTime(KCalCore::k2q(afterDateTime)));
return q2k(recur.getPreviousDateTime(k2q(afterDateTime)));
}
default:
return KCalCore::q2k(d->mRecurrence.getPreviousDateTime(KCalCore::k2q(afterDateTime)));
return q2k(d->mRecurrence.getPreviousDateTime(k2q(afterDateTime)));
}
}
......@@ -831,7 +831,7 @@ KDateTime KARecurrence::getPreviousDateTime(const KDateTime &afterDateTime) cons
*/
bool KARecurrence::recursOn(const QDate &dt, const KDateTime::Spec &timeSpec) const
{
if (!d->mRecurrence.recursOn(dt, KCalCore::specToZone(timeSpec))) {
if (!d->mRecurrence.recursOn(dt, specToZone(timeSpec))) {
return false;
}
if (dt != d->mRecurrence.startDate()) {
......@@ -844,7 +844,7 @@ bool KARecurrence::recursOn(const QDate &dt, const KDateTime::Spec &timeSpec) co
}
const RecurrenceRule::List rulelist = d->mRecurrence.rRules();
for (int rri = 0, rrend = rulelist.count(); rri < rrend; ++rri)
if (rulelist[rri]->recursOn(dt, KCalCore::specToZone(timeSpec))) {
if (rulelist[rri]->recursOn(dt, specToZone(timeSpec))) {
return true;
}
const auto dtlist = d->mRecurrence.rDateTimes();
......@@ -857,17 +857,17 @@ bool KARecurrence::recursOn(const QDate &dt, const KDateTime::Spec &timeSpec) co
bool KARecurrence::recursAt(const KDateTime &dt) const
{
return d->mRecurrence.recursAt(KCalCore::k2q(dt));
return d->mRecurrence.recursAt(k2q(dt));
}
TimeList KARecurrence::recurTimesOn(const QDate &date, const KDateTime::Spec &timeSpec) const
{
return d->mRecurrence.recurTimesOn(date, KCalCore::specToZone(timeSpec));
return d->mRecurrence.recurTimesOn(date, specToZone(timeSpec));
}
DateTimeList KARecurrence::timesInInterval(const KDateTime &start, const KDateTime &end) const
{
const auto l = d->mRecurrence.timesInInterval(KCalCore::k2q(start), KCalCore::k2q(end));
const auto l = d->mRecurrence.timesInInterval(k2q(start), k2q(end));
DateTimeList rv;
rv.reserve(l.size());
for (const auto &qdt : l) {
......@@ -898,7 +898,7 @@ void KARecurrence::setDuration(int duration)
int KARecurrence::durationTo(const KDateTime &dt) const
{
return d->mRecurrence.durationTo(KCalCore::k2q(dt));
return d->mRecurrence.durationTo(k2q(dt));
}
int KARecurrence::durationTo(const QDate &date) const
......@@ -935,8 +935,8 @@ int KARecurrence::Private::combineDurations(const RecurrenceRule *rrule1, const
count1 = count2 = 0;
}
// Get the two rules sorted by end date.
KDateTime end1 = KCalCore::q2k(rrule1->endDt());
KDateTime end2 = KCalCore::q2k(rrule2->endDt());
KDateTime end1 = q2k(rrule1->endDt());
KDateTime end2 = q2k(rrule2->endDt());
if (end1.date() == end2.date()) {
end = end1.date();
return count1 + count2;
......@@ -959,7 +959,7 @@ int KARecurrence::Private::combineDurations(const RecurrenceRule *rrule1, const
// Get the date of the next occurrence after the end of the earlier ending rule
RecurrenceRule rr(*rr1);
rr.setDuration(-1);
KDateTime next1(KCalCore::q2k(rr.getNextDate(KCalCore::k2q(end1))));
KDateTime next1(q2k(rr.getNextDate(k2q(end1))));
next1.setDateOnly(true);
if (!next1.isValid()) {
end = end1.date();
......@@ -971,7 +971,7 @@ int KARecurrence::Private::combineDurations(const RecurrenceRule *rrule1, const
end = end2.date();
return count1 + count2;
}
const QDate prev2 = rr2->getPreviousDate(KCalCore::k2q(next1)).date();
const QDate prev2 = rr2->getPreviousDate(k2q(next1)).date();
end = (prev2 > end1.date()) ? prev2 : end1.date();
}
if (count2) {
......@@ -1226,7 +1226,7 @@ void KARecurrence::setExDates(const DateList &exdates)
void KARecurrence::addExDateTime(const KDateTime &exdate)
{
d->mRecurrence.addExDateTime(KCalCore::k2q(exdate));
d->mRecurrence.addExDateTime(k2q(exdate));
}
void KARecurrence::addExDate(const QDate &exdate)
......
/*
This file is part of the kalarmcal library.
Copyright (c) 2017 Daniel Vrátil <dvratil@kde.org>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include "utils.h"
#include <KTimeZone>
#include <KSystemTimeZones>
#include <QDebug>
KDateTime::Spec KAlarmCal::zoneToSpec(const QTimeZone& zone)
{
if (!zone.isValid())
return KDateTime::Invalid;
if (zone == QTimeZone::utc())
return KDateTime::UTC;
if (zone == QTimeZone::systemTimeZone())
return KDateTime::LocalZone;
if (zone.id().startsWith("UTC")) {
return KDateTime::Spec(KDateTime::OffsetFromUTC, zone.offsetFromUtc(QDateTime::currentDateTimeUtc()));
} else {
return KSystemTimeZones::zone(QString::fromLatin1(zone.id()));
}
}
namespace {
QTimeZone resolveCustomTZ(const KTimeZone &ktz)
{
// First, let's try Microsoft
const auto msIana = QTimeZone::windowsIdToDefaultIanaId(ktz.name().toUtf8());
if (!msIana.isEmpty()) {
return QTimeZone(msIana);
}
int standardUtcOffset = 0;
bool matched = false;
const auto phases = ktz.phases();
for (const auto &phase : phases) {
if (!phase.isDst()) {
standardUtcOffset = phase.utcOffset();
matched = true;
break;
}
}
if (!matched) {
standardUtcOffset = ktz.currentOffset(Qt::UTC);
}
const auto candidates = QTimeZone::availableTimeZoneIds(standardUtcOffset);
QMap<int, QTimeZone> matchedCandidates;
for (const auto &tzid : candidates) {
const QTimeZone candidate(tzid);
// This would be a fallback
if (candidate.hasTransitions() != ktz.hasTransitions()) {
matchedCandidates.insert(0, candidate);
continue;
}
// Without transitions, we can't do any more precise matching, so just
// accept this candidate and be done with it
if (!candidate.hasTransitions() && !ktz.hasTransitions()) {
return candidate;
}
// Calculate how many transitions this candidate shares with the ktz.
// The candidate with the most matching transitions will win.
const auto transitions = ktz.transitions(QDateTime(), QDateTime::currentDateTimeUtc());
int matchedTransitions = 0;
for (auto it = transitions.rbegin(), end = transitions.rend(); it != end; ++it) {
const auto &transition = *it;
const QTimeZone::OffsetDataList candidateTransitions = candidate.transitions(transition.time(), transition.time());
if (candidateTransitions.isEmpty()) {
continue;
}
const auto candidateTransition = candidateTransitions[0];
const auto abvs = transition.phase().abbreviations();
for (const auto &abv : abvs) {
if (candidateTransition.abbreviation == QString::fromUtf8(abv)) {
++matchedTransitions;
break;
}
}
}
matchedCandidates.insert(matchedTransitions, candidate);
}
if (!matchedCandidates.isEmpty()) {
return matchedCandidates.value(matchedCandidates.lastKey());
}
return {};
}
}
QTimeZone KAlarmCal::specToZone(const KDateTime::Spec &spec)
{
switch (spec.type()) {
case KDateTime::Invalid:
return QTimeZone();
case KDateTime::LocalZone:
case KDateTime::ClockTime:
return QTimeZone::systemTimeZone();
case KDateTime::UTC:
return QTimeZone::utc();
default: {
auto tz = QTimeZone(spec.timeZone().name().toUtf8());
if (!tz.isValid()) {
tz = resolveCustomTZ(spec.timeZone());
qDebug() << "Resolved" << spec.timeZone().name() << "to" << tz.id();
}
return tz;
}
}
return QTimeZone::systemTimeZone();
}
QDateTime KAlarmCal::k2q(const KDateTime &kdt)
{
if (kdt.isValid()) {
return QDateTime(kdt.date(), kdt.time(), specToZone(kdt.timeSpec()));
} else {
return QDateTime();
}
}
KDateTime KAlarmCal::q2k(const QDateTime &qdt, bool allDay)
{
if (qdt.isValid()) {
KDateTime kdt(qdt.date(), qdt.time(), zoneToSpec(qdt.timeZone()));
kdt.setDateOnly(allDay && qdt.time() == QTime(0, 0, 0));
return kdt;
} else {