Skip to content

Commit

Permalink
Merge branch 'kf5-updated' into 'master'
Browse files Browse the repository at this point in the history
Update to use KF5-CalendarCore

See merge request mer-core/buteo-sync-plugin-caldav!75
  • Loading branch information
blam committed Dec 20, 2020
2 parents 1919280 + cba3ca1 commit 14e4c68
Show file tree
Hide file tree
Showing 19 changed files with 383 additions and 394 deletions.
6 changes: 3 additions & 3 deletions mkcal/caldavinvitationplugin.cpp
@@ -1,7 +1,7 @@
/*
* This file is part of buteo-sync-plugin-caldav package
*
* Copyright (C) 2019 Open Mobile Platform LLC
* Copyright (C) 2019 - 2020 Open Mobile Platform LLC
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
Expand All @@ -20,13 +20,13 @@

#include "caldavinvitationplugin.h"

#include <icalformat.h>
#include <KCalendarCore/ICalFormat>

#include <extendedcalendar.h>

#include <QDebug>

using namespace KCalCore;
using namespace KCalendarCore;

class CalDAVInvitationPluginPrivate
{
Expand Down
6 changes: 3 additions & 3 deletions mkcal/caldavinvitationplugin.h
@@ -1,7 +1,7 @@
/*
* This file is part of buteo-sync-plugin-caldav package
*
* Copyright (C) 2019 Open Mobile Platform LLC
* Copyright (C) 2019 - 2020 Open Mobile Platform LLC
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
Expand All @@ -21,15 +21,15 @@
#ifndef CALDAVINVITATIONPLUGIN_H
#define CALDAVINVITATIONPLUGIN_H

// KCalCore
// KCalendarCore
#include <invitationhandlerif.h>

// mKCal
#include <servicehandlerif.h>

#include <QtCore/QObject>

using namespace KCalCore;
using namespace KCalendarCore;

class CalDAVInvitationPluginPrivate;
class CalDAVInvitationPlugin : public QObject, public InvitationHandlerInterface, public ServiceInterface
Expand Down
2 changes: 1 addition & 1 deletion mkcal/mkcal.pro
Expand Up @@ -5,7 +5,7 @@ CONFIG += plugin
CONFIG += link_pkgconfig
PKGCONFIG += \
QmfClient \
libkcalcoren-qt5 \
KF5CalendarCore \
libmkcal-qt5

QT -= gui
Expand Down
2 changes: 1 addition & 1 deletion rpm/buteo-sync-plugin-caldav.spec
Expand Up @@ -11,7 +11,7 @@ BuildRequires: pkgconfig(Qt5Network)
BuildRequires: pkgconfig(libsignon-qt5)
BuildRequires: pkgconfig(libsailfishkeyprovider)
BuildRequires: pkgconfig(libmkcal-qt5) >= 0.5.20
BuildRequires: kcalcore-qt5-devel >= 4.10.2+9git27
BuildRequires: pkgconfig(KF5CalendarCore)
BuildRequires: pkgconfig(buteosyncfw5) >= 0.9.16
BuildRequires: pkgconfig(accounts-qt5)
BuildRequires: pkgconfig(signon-oauth2plugin)
Expand Down
4 changes: 2 additions & 2 deletions src/caldavclient.cpp
Expand Up @@ -148,7 +148,7 @@ bool CalDavClient::cleanUp()
}

mAccountId = accountId;
mKCal::ExtendedCalendar::Ptr calendar = mKCal::ExtendedCalendar::Ptr(new mKCal::ExtendedCalendar(KDateTime::Spec::UTC()));
mKCal::ExtendedCalendar::Ptr calendar = mKCal::ExtendedCalendar::Ptr(new mKCal::ExtendedCalendar(QTimeZone::utc()));
mKCal::ExtendedStorage::Ptr storage = mKCal::ExtendedCalendar::defaultStorage(calendar);
if (!storage->open()) {
calendar->close();
Expand Down Expand Up @@ -661,7 +661,7 @@ void CalDavClient::syncCalendars(const QList<PropFind::CalendarInfo> &allCalenda
QLatin1String("No calendars for this account"));
return;
}
mCalendar = mKCal::ExtendedCalendar::Ptr(new mKCal::ExtendedCalendar(KDateTime::Spec::UTC()));
mCalendar = mKCal::ExtendedCalendar::Ptr(new mKCal::ExtendedCalendar(QTimeZone::utc()));
mStorage = mKCal::ExtendedCalendar::defaultStorage(mCalendar);
if (!mStorage || !mStorage->open()) {
syncFinished(Buteo::SyncResults::DATABASE_FAILURE,
Expand Down
1 change: 0 additions & 1 deletion src/caldavclient.h
Expand Up @@ -34,7 +34,6 @@
#include <QSet>
#include <QScopedPointer>

#include <incidence.h>
#include <extendedstorage.h>

#include <ClientPlugin.h>
Expand Down
2 changes: 0 additions & 2 deletions src/delete.h
Expand Up @@ -26,8 +26,6 @@

#include "request.h"

#include <incidence.h>

#include <QObject>
#include <QNetworkReply>
#include <QSslError>
Expand Down
82 changes: 39 additions & 43 deletions src/incidencehandler.cpp
Expand Up @@ -27,8 +27,8 @@

#include <LogMacros.h>

#include <memorycalendar.h>
#include <icalformat.h>
#include <KCalendarCore/MemoryCalendar>
#include <KCalendarCore/ICalFormat>

#define PROP_DTEND_ADDED_USING_DTSTART "dtend-added-as-dtstart"

Expand All @@ -45,30 +45,30 @@ IncidenceHandler::~IncidenceHandler()
// Since the incidence may be an occurrence or recurring series incidence,
// we cannot simply convert the incidence to iCal data, but instead we have to
// upsync an .ics containing the whole recurring series.
QString IncidenceHandler::toIcs(const KCalCore::Incidence::Ptr incidence,
const KCalCore::Incidence::List instances)
QString IncidenceHandler::toIcs(const KCalendarCore::Incidence::Ptr incidence,
const KCalendarCore::Incidence::List instances)
{
KCalCore::Incidence::Ptr exportableIncidence = IncidenceHandler::incidenceToExport(incidence, instances);
KCalendarCore::Incidence::Ptr exportableIncidence = IncidenceHandler::incidenceToExport(incidence, instances);

// create an in-memory calendar
// add to it the required incidences (ie, check if has recurrenceId -> load parent and all instances; etc)
// for each of those, we need to do the IncidenceToExport() modifications first
// then, export from that calendar to .ics file.
KCalCore::MemoryCalendar::Ptr memoryCalendar(new KCalCore::MemoryCalendar(KDateTime::UTC));
KCalendarCore::MemoryCalendar::Ptr memoryCalendar(new KCalendarCore::MemoryCalendar(QTimeZone::utc()));
// store the base recurring event into the in-memory calendar
if (!memoryCalendar->addIncidence(exportableIncidence)) {
LOG_WARNING("Unable to add base series event to in-memory calendar for incidence:"
<< incidence->uid() << ":" << incidence->recurrenceId().toString());
return QString();
}
// now create the persistent occurrences in the in-memory calendar
for (KCalCore::Incidence::Ptr instance : instances) {
for (KCalendarCore::Incidence::Ptr instance : instances) {
// We cannot call dissociateSingleOccurrence() on the MemoryCalendar
// as that's an mKCal specific function.
// We cannot call dissociateOccurrence() because that function
// takes only a QDate instead of a KDateTime recurrenceId.
// Thus, we need to manually create an exception occurrence.
KCalCore::Incidence::Ptr exportableOccurrence(exportableIncidence->clone());
KCalendarCore::Incidence::Ptr exportableOccurrence(exportableIncidence->clone());
exportableOccurrence->setCreated(instance->created());
exportableOccurrence->setRevision(instance->revision());
exportableOccurrence->clearRecurrence();
Expand All @@ -81,23 +81,23 @@ QString IncidenceHandler::toIcs(const KCalCore::Incidence::Ptr incidence,
<< instance->uid() << instance->recurrenceId().toString());
return QString();
} else {
KCalCore::Incidence::Ptr reloadedOccurrence = memoryCalendar->incidence(exportableIncidence->uid(), instance->recurrenceId());
KCalendarCore::Incidence::Ptr reloadedOccurrence = memoryCalendar->incidence(exportableIncidence->uid(), instance->recurrenceId());
if (!reloadedOccurrence) {
LOG_WARNING("Unable to find this incidence within in-memory calendar for export:"
<< exportableIncidence->uid() << instance->recurrenceId().toString());
return QString();
}
*reloadedOccurrence.staticCast<KCalCore::IncidenceBase>() = *IncidenceHandler::incidenceToExport(instance).staticCast<KCalCore::IncidenceBase>();
*reloadedOccurrence.staticCast<KCalendarCore::IncidenceBase>() = *IncidenceHandler::incidenceToExport(instance).staticCast<KCalendarCore::IncidenceBase>();
}
}

KCalCore::ICalFormat icalFormat;
KCalendarCore::ICalFormat icalFormat;
return icalFormat.toString(memoryCalendar, QString(), false);
}

KCalCore::Incidence::Ptr IncidenceHandler::incidenceToExport(KCalCore::Incidence::Ptr sourceIncidence, const KCalCore::Incidence::List &instances)
KCalendarCore::Incidence::Ptr IncidenceHandler::incidenceToExport(KCalendarCore::Incidence::Ptr sourceIncidence, const KCalendarCore::Incidence::List &instances)
{
KCalCore::Incidence::Ptr incidence = QSharedPointer<KCalCore::Incidence>(sourceIncidence->clone());
KCalendarCore::Incidence::Ptr incidence = QSharedPointer<KCalendarCore::Incidence>(sourceIncidence->clone());

// check to see if the UID is of the special form: NBUID:NotebookUid:EventUid. If so, trim it.
if (incidence->uid().startsWith(QStringLiteral("NBUID:"))) {
Expand All @@ -115,33 +115,36 @@ KCalCore::Incidence::Ptr IncidenceHandler::incidenceToExport(KCalCore::Incidence
incidence->removeCustomProperty("buteo", "etag");
const QStringList &comments(incidence->comments());
for (const QString &comment : comments) {
if (comment.startsWith("buteo:caldav:uri:") ||
comment.startsWith("buteo:caldav:detached-and-synced") ||
comment.startsWith("buteo:caldav:etag:")) {
if ((comment.startsWith("buteo:caldav:uri:") ||
comment.startsWith("buteo:caldav:detached-and-synced") ||
comment.startsWith("buteo:caldav:etag:"))
&& incidence->removeComment(comment)) {
LOG_DEBUG("Discarding buteo-prefixed comment:" << comment);
incidence->removeComment(comment);
}
}

// The default storage implementation applies the organizer as an attendee by default.
// Undo this as it turns the incidence into a scheduled event requiring acceptance/rejection/etc.
const KCalCore::Person::Ptr organizer = incidence->organizer();
if (organizer) {
const KCalCore::Attendee::List attendees = incidence->attendees();
for (const KCalCore::Attendee::Ptr &attendee : attendees) {
if (attendee->email() == organizer->email() && attendee->fullName() == organizer->fullName()) {
LOG_DEBUG("Discarding organizer as attendee" << attendee->fullName());
incidence->deleteAttendee(attendee);
const KCalendarCore::Person &organizer = incidence->organizer();
if (!organizer.isEmpty()) {
KCalendarCore::Attendee::List attendees = incidence->attendees();
KCalendarCore::Attendee::List::Iterator it = attendees.begin();
while (it != attendees.end()) {
if (it->email() == organizer.email() && it->fullName() == organizer.fullName()) {
LOG_DEBUG("Discarding organizer as attendee" << it->fullName());
it = attendees.erase(it);
} else {
LOG_DEBUG("Not discarding attendee:" << attendee->fullName() << attendee->email() << ": not organizer:" << organizer->fullName() << organizer->email());
LOG_DEBUG("Not discarding attendee:" << it->fullName() << it->email() << ": not organizer:" << organizer.fullName() << organizer.email());
it++;
}
}
incidence->setAttendees(attendees);
}

// remove EXDATE values from the recurring incidence which correspond to the persistent occurrences (instances)
if (incidence->recurs()) {
for (KCalCore::Incidence::Ptr instance : instances) {
KCalCore::DateTimeList exDateTimes = incidence->recurrence()->exDateTimes();
for (KCalendarCore::Incidence::Ptr instance : instances) {
KCalendarCore::DateTimeList exDateTimes = incidence->recurrence()->exDateTimes();
exDateTimes.removeAll(instance->recurrenceId());
incidence->recurrence()->setExDateTimes(exDateTimes);
LOG_DEBUG("Discarding exdate:" << instance->recurrenceId().toString());
Expand All @@ -150,27 +153,27 @@ KCalCore::Incidence::Ptr IncidenceHandler::incidenceToExport(KCalCore::Incidence

// Icalformat from kcalcore converts second-type duration into day-type duration
// whenever possible. We do the same to have consistent comparisons.
const KCalCore::Alarm::List alarms = incidence->alarms();
for (KCalCore::Alarm::Ptr alarm : alarms) {
const KCalendarCore::Alarm::List alarms = incidence->alarms();
for (KCalendarCore::Alarm::Ptr alarm : alarms) {
if (!alarm->hasTime()) {
KCalCore::Duration offset(0);
KCalendarCore::Duration offset(0);
if (alarm->hasEndOffset())
offset = alarm->endOffset();
else
offset = alarm->startOffset();
if (!offset.isDaily() && !(offset.value() % (60 * 60 * 24))) {
LOG_DEBUG("Converting to day-type duration " << offset.asDays());
if (alarm->hasEndOffset())
alarm->setEndOffset(KCalCore::Duration(offset.asDays(), KCalCore::Duration::Days));
alarm->setEndOffset(KCalendarCore::Duration(offset.asDays(), KCalendarCore::Duration::Days));
else
alarm->setStartOffset(KCalCore::Duration(offset.asDays(), KCalCore::Duration::Days));
alarm->setStartOffset(KCalendarCore::Duration(offset.asDays(), KCalendarCore::Duration::Days));
}
}
}

switch (incidence->type()) {
case KCalCore::IncidenceBase::TypeEvent: {
KCalCore::Event::Ptr event = incidence.staticCast<KCalCore::Event>();
case KCalendarCore::IncidenceBase::TypeEvent: {
KCalendarCore::Event::Ptr event = incidence.staticCast<KCalendarCore::Event>();
bool eventIsAllDay = event->allDay();
if (eventIsAllDay) {
bool sendWithoutDtEnd = !event->customProperty("buteo", PROP_DTEND_ADDED_USING_DTSTART).isEmpty()
Expand All @@ -181,24 +184,17 @@ KCalCore::Incidence::Ptr IncidenceHandler::incidenceToExport(KCalCore::Incidence
// A single-day all-day event was received without a DTEND, and it is still a single-day
// all-day event, so remove the DTEND before upsyncing.
LOG_DEBUG("Removing DTEND from" << incidence->uid());
event->setDtEnd(KDateTime());
event->setDtEnd(QDateTime());
}
}

if (event->dtStart().isDateOnly()) {
KDateTime dt = KDateTime(event->dtStart().date(), KDateTime::Spec::ClockTime());
dt.setDateOnly(true);
event->setDtStart(dt);
LOG_DEBUG("Stripping time from date-only DTSTART:" << dt.toString());
}

// setting dtStart/End changes the allDay value, so ensure it is still set to true if needed.
if (eventIsAllDay) {
event->setAllDay(true);
}
break;
}
case KCalCore::IncidenceBase::TypeTodo:
case KCalendarCore::IncidenceBase::TypeTodo:
break;
default:
LOG_DEBUG("Incidence type not supported; cannot create proper exportable version");
Expand Down
16 changes: 8 additions & 8 deletions src/incidencehandler.h
Expand Up @@ -23,23 +23,23 @@
#ifndef INCIDENCEHANDLER_P_H
#define INCIDENCEHANDLER_P_H

#include <incidence.h>
#include <event.h>
#include <todo.h>
#include <journal.h>
#include <attendee.h>
#include <KCalendarCore/Incidence>
#include <KCalendarCore/Event>
#include <KCalendarCore/Todo>
#include <KCalendarCore/Journal>
#include <KCalendarCore/Attendee>

class IncidenceHandler
{
public:
static QString toIcs(const KCalCore::Incidence::Ptr incidence,
const KCalCore::Incidence::List instances = KCalCore::Incidence::List());
static QString toIcs(const KCalendarCore::Incidence::Ptr incidence,
const KCalendarCore::Incidence::List instances = KCalendarCore::Incidence::List());

private:
IncidenceHandler();
~IncidenceHandler();

static KCalCore::Incidence::Ptr incidenceToExport(KCalCore::Incidence::Ptr sourceIncidence, const KCalCore::Incidence::List &instances = KCalCore::Incidence::List());
static KCalendarCore::Incidence::Ptr incidenceToExport(KCalendarCore::Incidence::Ptr sourceIncidence, const KCalendarCore::Incidence::List &instances = KCalendarCore::Incidence::List());

friend class tst_NotebookSyncAgent;
friend class tst_IncidenceHandler;
Expand Down

0 comments on commit 14e4c68

Please sign in to comment.