diff --git a/CMakeLists.txt b/CMakeLists.txt index e8a70ca..42b8978 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,97 +1,97 @@ cmake_minimum_required(VERSION 3.5) set(PIM_VERSION "5.11.40") project(Akonadi-Calendar VERSION ${PIM_VERSION}) # ECM setup set(KF5_MIN_VERSION "5.59.0") find_package(ECM ${KF5_MIN_VERSION} CONFIG REQUIRED) set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH}) include(GenerateExportHeader) include(ECMGenerateHeaders) include(ECMGeneratePriFile) include(ECMSetupVersion) include(FeatureSummary) include(KDEInstallDirs) include(KDECMakeSettings) include(KDEFrameworkCompilerSettings NO_POLICY_SCOPE) include(ECMQtDeclareLoggingCategory) set(AKONADICALENDAR_LIB_VERSION ${PIM_VERSION}) -set(CALENDARCORE_LIB_VERSION "5.11.44") +set(CALENDARCORE_LIB_VERSION "5.11.45") set(AKONADICONTACT_LIB_VERSION "5.11.40") set(AKONADI_LIB_VERSION "5.11.40") set(MAILTRANSPORT_LIB_VERSION "5.11.40") set(KCONTACTS_LIB_VERSION "5.11.40") set(CALENDARUTILS_LIB_VERSION "5.11.40") set(IDENTITYMANAGEMENT_LIB_VERSION "5.11.40") ecm_setup_version(PROJECT VARIABLE_PREFIX AKONADICALENDAR VERSION_HEADER "${CMAKE_CURRENT_BINARY_DIR}/akonadi-calendar_version.h" PACKAGE_VERSION_FILE "${CMAKE_CURRENT_BINARY_DIR}/KF5AkonadiCalendarConfigVersion.cmake" SOVERSION 5 ) configure_file(akonadi-calendar-version.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/src/akonadi-calendar-version.h @ONLY) if(BUILD_TESTING) add_definitions(-DBUILD_TESTING) endif() ########### Find packages ########### find_package(KF5I18n ${KF5_MIN_VERSION} CONFIG REQUIRED) find_package(KF5WidgetsAddons ${KF5_MIN_VERSION} CONFIG REQUIRED) find_package(KF5XmlGui ${KF5_MIN_VERSION} CONFIG REQUIRED) find_package(KF5KIO ${KF5_MIN_VERSION} CONFIG REQUIRED) find_package(KF5Codecs ${KF5_MIN_VERSION} CONFIG REQUIRED) find_package(KF5IconThemes ${KF5_MIN_VERSION} CONFIG REQUIRED) find_package(KF5DBusAddons ${KF5_MIN_VERSION} CONFIG REQUIRED) find_package(KF5MailTransportAkonadi ${MAILTRANSPORT_LIB_VERSION} CONFIG REQUIRED) find_package(KF5IdentityManagement ${IDENTITYMANAGEMENT_LIB_VERSION} CONFIG REQUIRED) find_package(KF5CalendarCore ${CALENDARCORE_LIB_VERSION} CONFIG REQUIRED) find_package(KF5CalendarUtils ${CALENDARUTILS_LIB_VERSION} CONFIG REQUIRED) find_package(KF5Akonadi ${AKONADI_LIB_VERSION} CONFIG REQUIRED) find_package(KF5AkonadiContact ${AKONADICONTACT_LIB_VERSION} CONFIG REQUIRED) ########### Targets ########### add_definitions(-DQT_DISABLE_DEPRECATED_BEFORE=0x060000) add_definitions(-DQT_NO_FOREACH) add_subdirectory(src) add_subdirectory(serializers) if (BUILD_TESTING) add_subdirectory(autotests) endif () ########### CMake Config Files ########### set(CMAKECONFIG_INSTALL_DIR "${KDE_INSTALL_CMAKEPACKAGEDIR}/KF5AkonadiCalendar") configure_package_config_file( "${CMAKE_CURRENT_SOURCE_DIR}/KF5AkonadiCalendarConfig.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/KF5AkonadiCalendarConfig.cmake" INSTALL_DESTINATION ${CMAKECONFIG_INSTALL_DIR} ) install(FILES "${CMAKE_CURRENT_BINARY_DIR}/KF5AkonadiCalendarConfig.cmake" "${CMAKE_CURRENT_BINARY_DIR}/KF5AkonadiCalendarConfigVersion.cmake" DESTINATION "${CMAKECONFIG_INSTALL_DIR}" COMPONENT Devel ) install(EXPORT KF5AkonadiCalendarTargets DESTINATION "${CMAKECONFIG_INSTALL_DIR}" FILE KF5AkonadiCalendarTargets.cmake NAMESPACE KF5::) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/akonadi-calendar_version.h DESTINATION ${KDE_INSTALL_INCLUDEDIR_KF5} COMPONENT Devel ) install(FILES akonadi-calendar.renamecategories akonadi-calendar.categories DESTINATION ${KDE_INSTALL_LOGGINGCATEGORIESDIR}) feature_summary(WHAT ALL FATAL_ON_MISSING_REQUIRED_PACKAGES) diff --git a/serializers/akonadi_serializer_kcalcore.cpp b/serializers/akonadi_serializer_kcalcore.cpp index c9a5085..999f86c 100644 --- a/serializers/akonadi_serializer_kcalcore.cpp +++ b/serializers/akonadi_serializer_kcalcore.cpp @@ -1,365 +1,365 @@ /* Copyright (c) 2007 Volker Krause 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 "akonadi_serializer_kcalcore.h" #include #include #include #include #include #include #include #include #include "serializer_debug.h" using namespace KCalCore; using namespace KCalUtils; using namespace Akonadi; SerializerPluginKCalCore::SerializerPluginKCalCore() { } //// ItemSerializerPlugin interface bool SerializerPluginKCalCore::deserialize(Item &item, const QByteArray &label, QIODevice &data, int version) { Q_UNUSED(version); if (label != Item::FullPayload) { return false; } qint32 type; quint32 magic, incidenceVersion; QDataStream input(&data); input >> magic; input >> incidenceVersion; input >> type; data.seek(0); Incidence::Ptr incidence; if (magic == IncidenceBase::magicSerializationIdentifier()) { IncidenceBase::Ptr base; switch (static_cast(type)) { case KCalCore::Incidence::TypeEvent: base = Event::Ptr(new Event()); break; case KCalCore::Incidence::TypeTodo: base = Todo::Ptr(new Todo()); break; case KCalCore::Incidence::TypeJournal: base = Journal::Ptr(new Journal()); break; case KCalCore::Incidence::TypeFreeBusy: base = FreeBusy::Ptr(new FreeBusy()); break; case KCalCore::Incidence::TypeUnknown: return false; } input >> base; incidence = base.staticCast(); } else { // Use the old format incidence = mFormat.readIncidence(data.readAll()); } if (!incidence) { qCWarning(AKONADI_SERIALIZER_CALENDAR_LOG) << "Failed to parse incidence! Item id = " << item.id() << "Storage collection id " << item.storageCollectionId() << "parentCollectionId = " << item.parentCollection().id(); data.seek(0); qCWarning(AKONADI_SERIALIZER_CALENDAR_LOG) << QString::fromUtf8(data.readAll()); return false; } item.setPayload(incidence); return true; } void SerializerPluginKCalCore::serialize(const Item &item, const QByteArray &label, QIODevice &data, int &version) { Q_UNUSED(version); if (label != Item::FullPayload || !item.hasPayload()) { return; } Incidence::Ptr i = item.payload(); // Using an env variable for now while testing if (qgetenv("KCALCORE_BINARY_SERIALIZER") == QByteArray("1")) { QDataStream output(&data); IncidenceBase::Ptr base = i; output << base; } else { // ### I guess this can be done without hardcoding stuff data.write("BEGIN:VCALENDAR\nPRODID:-//K Desktop Environment//NONSGML libkcal 4.3//EN\nVERSION:2.0\nX-KDE-ICAL-IMPLEMENTATION-VERSION:1.0\n"); data.write(mFormat.toRawString(i)); data.write("\nEND:VCALENDAR"); } } //// DifferencesAlgorithmInterface static bool compareString(const QString &left, const QString &right) { if (left.isEmpty() && right.isEmpty()) { return true; } else { return left == right; } } static QString toString(const Attendee &attendee) { return attendee.name() + QLatin1Char('<') + attendee.email() + QLatin1Char('>'); } static QString toString(const Alarm::Ptr &) { return QString(); } -static QString toString(const Attachment::Ptr &) +static QString toString(const Attachment &) { return QString(); } static QString toString(const QDate &date) { return date.toString(); } static QString toString(const QDateTime &dateTime) { return dateTime.toString(); } static QString toString(const QString &str) { return str; } static QString toString(bool value) { if (value) { return i18n("Yes"); } else { return i18n("No"); } } template static void compareList(AbstractDifferencesReporter *reporter, const QString &id, const C &left, const C &right) { for (typename C::const_iterator it = left.begin(), end = left.end(); it != end; ++it) { if (!right.contains(*it)) { reporter->addProperty(AbstractDifferencesReporter::AdditionalLeftMode, id, toString(*it), QString()); } } for (typename C::const_iterator it = right.begin(), end = right.end(); it != end; ++it) { if (!left.contains(*it)) { reporter->addProperty(AbstractDifferencesReporter::AdditionalRightMode, id, QString(), toString(*it)); } } } static void compareIncidenceBase(AbstractDifferencesReporter *reporter, const IncidenceBase::Ptr &left, const IncidenceBase::Ptr &right) { compareList(reporter, i18n("Attendees"), left->attendees(), right->attendees()); if (!compareString(left->organizer().fullName(), right->organizer().fullName())) { reporter->addProperty(AbstractDifferencesReporter::ConflictMode, i18n("Organizer"), left->organizer().fullName(), right->organizer().fullName()); } if (!compareString(left->uid(), right->uid())) { reporter->addProperty(AbstractDifferencesReporter::ConflictMode, i18n("UID"), left->uid(), right->uid()); } if (left->allDay() != right->allDay()) { reporter->addProperty(AbstractDifferencesReporter::ConflictMode, i18n("Is all-day"), toString(left->allDay()), toString(right->allDay())); } if (left->hasDuration() != right->hasDuration()) { reporter->addProperty(AbstractDifferencesReporter::ConflictMode, i18n("Has duration"), toString(left->hasDuration()), toString(right->hasDuration())); } if (left->duration() != right->duration()) { reporter->addProperty(AbstractDifferencesReporter::ConflictMode, i18n("Duration"), QString::number(left->duration().asSeconds()), QString::number(right->duration().asSeconds())); } } static void compareIncidence(AbstractDifferencesReporter *reporter, const Incidence::Ptr &left, const Incidence::Ptr &right) { if (!compareString(left->description(), right->description())) { reporter->addProperty(AbstractDifferencesReporter::ConflictMode, i18n("Description"), left->description(), right->description()); } if (!compareString(left->summary(), right->summary())) { reporter->addProperty(AbstractDifferencesReporter::ConflictMode, i18n("Summary"), left->summary(), right->summary()); } if (left->status() != right->status()) { reporter->addProperty(AbstractDifferencesReporter::ConflictMode, i18n("Status"), Stringify::incidenceStatus(left), Stringify::incidenceStatus(right)); } if (left->secrecy() != right->secrecy()) { reporter->addProperty(AbstractDifferencesReporter::ConflictMode, i18n("Secrecy"), toString(left->secrecy()), toString(right->secrecy())); } if (left->priority() != right->priority()) { reporter->addProperty(AbstractDifferencesReporter::ConflictMode, i18n("Priority"), toString(left->priority()), toString(right->priority())); } if (!compareString(left->location(), right->location())) { reporter->addProperty(AbstractDifferencesReporter::ConflictMode, i18n("Location"), left->location(), right->location()); } compareList(reporter, i18n("Categories"), left->categories(), right->categories()); compareList(reporter, i18n("Alarms"), left->alarms(), right->alarms()); compareList(reporter, i18n("Resources"), left->resources(), right->resources()); compareList(reporter, i18n("Attachments"), left->attachments(), right->attachments()); compareList(reporter, i18n("Exception Dates"), left->recurrence()->exDates(), right->recurrence()->exDates()); compareList(reporter, i18n("Exception Times"), left->recurrence()->exDateTimes(), right->recurrence()->exDateTimes()); // TODO: recurrence dates and date/times, exrules, rrules if (left->created() != right->created()) { reporter->addProperty(AbstractDifferencesReporter::ConflictMode, i18n("Created"), left->created().toString(), right->created().toString()); } if (!compareString(left->relatedTo(), right->relatedTo())) { reporter->addProperty(AbstractDifferencesReporter::ConflictMode, i18n("Related Uid"), left->relatedTo(), right->relatedTo()); } } static void compareEvent(AbstractDifferencesReporter *reporter, const Event::Ptr &left, const Event::Ptr &right) { if (left->dtStart() != right->dtStart()) { reporter->addProperty(AbstractDifferencesReporter::ConflictMode, i18n("Start time"), left->dtStart().toString(), right->dtStart().toString()); } if (left->hasEndDate() != right->hasEndDate()) { reporter->addProperty(AbstractDifferencesReporter::ConflictMode, i18n("Has End Date"), toString(left->hasEndDate()), toString(right->hasEndDate())); } if (left->dtEnd() != right->dtEnd()) { reporter->addProperty(AbstractDifferencesReporter::ConflictMode, i18n("End Date"), left->dtEnd().toString(), right->dtEnd().toString()); } // TODO: check transparency } static void compareTodo(AbstractDifferencesReporter *reporter, const Todo::Ptr &left, const Todo::Ptr &right) { if (left->hasStartDate() != right->hasStartDate()) { reporter->addProperty(AbstractDifferencesReporter::ConflictMode, i18n("Has Start Date"), toString(left->hasStartDate()), toString(right->hasStartDate())); } if (left->hasDueDate() != right->hasDueDate()) { reporter->addProperty(AbstractDifferencesReporter::ConflictMode, i18n("Has Due Date"), toString(left->hasDueDate()), toString(right->hasDueDate())); } if (left->dtDue() != right->dtDue()) { reporter->addProperty(AbstractDifferencesReporter::ConflictMode, i18n("Due Date"), left->dtDue().toString(), right->dtDue().toString()); } if (left->hasCompletedDate() != right->hasCompletedDate()) { reporter->addProperty(AbstractDifferencesReporter::ConflictMode, i18n("Has Complete Date"), toString(left->hasCompletedDate()), toString(right->hasCompletedDate())); } if (left->percentComplete() != right->percentComplete()) { reporter->addProperty(AbstractDifferencesReporter::ConflictMode, i18n("Complete"), QString::number(left->percentComplete()), QString::number(right->percentComplete())); } if (left->completed() != right->completed()) { reporter->addProperty(AbstractDifferencesReporter::ConflictMode, i18n("Completed"), toString(left->completed()), toString(right->completed())); } } void SerializerPluginKCalCore::compare(Akonadi::AbstractDifferencesReporter *reporter, const Akonadi::Item &leftItem, const Akonadi::Item &rightItem) { Q_ASSERT(reporter); Q_ASSERT(leftItem.hasPayload()); Q_ASSERT(rightItem.hasPayload()); const Incidence::Ptr leftIncidencePtr = leftItem.payload(); const Incidence::Ptr rightIncidencePtr = rightItem.payload(); if (leftIncidencePtr->type() == Incidence::TypeEvent) { reporter->setLeftPropertyValueTitle(i18n("Changed Event")); reporter->setRightPropertyValueTitle(i18n("Conflicting Event")); } else if (leftIncidencePtr->type() == Incidence::TypeTodo) { reporter->setLeftPropertyValueTitle(i18n("Changed Todo")); reporter->setRightPropertyValueTitle(i18n("Conflicting Todo")); } compareIncidenceBase(reporter, leftIncidencePtr, rightIncidencePtr); compareIncidence(reporter, leftIncidencePtr, rightIncidencePtr); const Event::Ptr leftEvent = leftIncidencePtr.dynamicCast(); const Event::Ptr rightEvent = rightIncidencePtr.dynamicCast(); if (leftEvent && rightEvent) { compareEvent(reporter, leftEvent, rightEvent); } else { const Todo::Ptr leftTodo = leftIncidencePtr.dynamicCast(); const Todo::Ptr rightTodo = rightIncidencePtr.dynamicCast(); if (leftTodo && rightTodo) { compareTodo(reporter, leftTodo, rightTodo); } } } //// GidExtractorInterface QString SerializerPluginKCalCore::extractGid(const Item &item) const { if (!item.hasPayload()) { return QString(); } return item.payload()->instanceIdentifier(); }