diff --git a/CMakeLists.txt b/CMakeLists.txt index b6196fe..3b349ec 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,172 +1,176 @@ project(Libkolab) cmake_minimum_required(VERSION 2.8.9) option(BUILD_TESTS "Build the tests" TRUE) option(PYTHON_BINDINGS "Build bindings for python" FALSE) option(PHP_BINDINGS "Build bindings for php" FALSE) set(Libkolab_MODULE_DIR ${Libkolab_SOURCE_DIR}/cmake/modules) set(CMAKE_MODULE_PATH ${Libkolab_MODULE_DIR}) # only available from cmake-2.8.0 if(${CMAKE_MAJOR_VERSION} EQUAL 2 AND ${CMAKE_MINOR_VERSION} GREATER 7) cmake_policy(SET CMP0012 NEW) endif() # only available from cmake-2.8.4 if(${CMAKE_MAJOR_VERSION} EQUAL 2 AND ${CMAKE_MINOR_VERSION} GREATER 7 AND ${CMAKE_PATCH_VERSION} GREATER 3) cmake_policy(SET CMP0017 NEW) endif() # Versioning # x.y.z scheme # Development versions are only x.y # # i.e. # 0.1 (0.1 development version towards 0.1.0) # 0.1.0 (first release) # 0.1.1 (patch release for 0.1.0) # 0.2 (0.2 development version towards 0.2.0) set(Libkolab_VERSION_MAJOR 3) set(Libkolab_VERSION_MINOR 1) # Enable the full x.y.z version only for release versions set(Libkolab_VERSION_PATCH 0) #set(Libkolab_VERSION ${Libkolab_VERSION_MAJOR}.${Libkolab_VERSION_MINOR}.${Libkolab_VERSION_PATCH}) set(Libkolab_VERSION ${Libkolab_VERSION_MAJOR}.${Libkolab_VERSION_MINOR}) set(Libkolab_VERSION_STRING ${CMAKE_PROJECT_NAME}-${Libkolab_VERSION}) # set up install directories. set(LIB_INSTALL_DIR lib${LIB_SUFFIX} CACHE STRING "The directories where to install libraries to") set(INCLUDE_INSTALL_DIR include CACHE STRING "The directory where to install headers to") set(INCLUDE_INSTALL_DIR ${INCLUDE_INSTALL_DIR}/kolab) set(CMAKECONFIG_INSTALL_DIR ${LIB_INSTALL_DIR}/cmake/Libkolab) # Make relative paths absolute (needed later on) foreach(p LIB INCLUDE CMAKECONFIG) set(var ${p}_INSTALL_DIR) if(NOT IS_ABSOLUTE "${${var}}") set(${var} "${CMAKE_INSTALL_PREFIX}/${${var}}") endif() endforeach() include(MacroLogFeature) find_package(Qt5 REQUIRED Core Xml) # FIXME: Seems to be required for libkolabxml, but should be fixed in libkolabxml set(Boost_USE_MULTITHREADED ON) find_package(Boost REQUIRED COMPONENTS thread system) # Do the building find_package(Libkolabxml 1.1.1 REQUIRED) macro_log_feature(Libkolabxml_FOUND "Libkolabxml" "Kolab XML Format 3 serializing library" "https://git.kolab.org/diffusion/LKX/" TRUE "1.1.1" "Required for reading/writing Kolab XML Objects") set(QT_REQUIRED_VERSION "5.9.0") if (Qt5_POSITION_INDEPENDENT_CODE) #Requires cmake 2.8.9 (same as -fPIC on gcc) set(CMAKE_POSITION_INDEPENDENT_CODE ON) endif() include(FindPackageHandleStandardArgs) -find_package(KF5CalendarCore "5.12.1" CONFIG REQUIRED) +find_package(KF5CalendarCore "5.9.3" CONFIG REQUIRED) +if (KF5CalendarCore_VERSION VERSION_LESS "5.12.1") + message("Building with legacy kcalcore") + add_definitions(-DLEGACY_KCALCORE=1) +endif() find_package(KF5Mime "4.84.0" CONFIG REQUIRED) find_package(SWIG) #Show summary of found libraries macro_display_feature_log() set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wnon-virtual-dtor -Wno-long-long -ansi -Wundef -Wcast-align -Wchar-subscripts -Wall -W -Wpointer-arith -Wformat-security -fno-exceptions -DQT_NO_EXCEPTIONS -fno-common -Woverloaded-virtual -fno-threadsafe-statics -fvisibility=hidden -Werror=return-type -fvisibility-inlines-hidden -fexceptions -UQT_NO_EXCEPTIONS -fPIC -g -std=c++11") # message("${CMAKE_CXX_FLAGS}") set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -DQT_NO_DEBUG") include_directories( ${QT_INCLUDES} ${CMAKE_BINARY_DIR} ${Libkolabxml_INCLUDES} ./ ) configure_file(libkolab-version.h.cmake "${CMAKE_BINARY_DIR}/libkolab-version.h" @ONLY) add_subdirectory(conversion) add_subdirectory(calendaring) QT5_WRAP_CPP(CALENDARING_MOC calendaring/event.h) set(KOLAB_SRCS kolabformat/xmlobject.cpp kolabformat/formathelpers.cpp kolabformat/errorhandler.cpp mime/mimeutils.cpp ${CONVERSION_SRCS} ${kolabformatv2_SRCS} ${CALENDARING_SRCS} ) set(KOLAB_LINK_LIBRARIES ${Libkolabxml_LIBRARIES} KF5::CalendarCore KF5::Mime Qt5::Core Qt5::Xml ) if(BUILD_TESTS) find_package(Qt5Test REQUIRED) #for tests only enable_testing() add_library(kolab_static STATIC ${KOLAB_SRCS}) target_link_libraries(kolab_static ${KOLAB_LINK_LIBRARIES} Qt5::Test) add_subdirectory(tests) endif(BUILD_TESTS) add_library(kolab SHARED ${KOLAB_SRCS}) target_link_libraries(kolab ${KOLAB_LINK_LIBRARIES}) set_target_properties(kolab PROPERTIES VERSION ${Libkolab_VERSION} SOVERSION ${Libkolab_VERSION_MAJOR}) install(TARGETS kolab EXPORT LibkolabExport RUNTIME DESTINATION ${BIN_INSTALL_DIR} LIBRARY DESTINATION ${LIB_INSTALL_DIR} ARCHIVE DESTINATION ${LIB_INSTALL_DIR} ) install(FILES kolab_export.h kolabformat/kolabdefinitions.h kolabformat/formathelpers.h kolabformat/errorhandler.h kolabformat/xmlobject.h conversion/commonconversion.h DESTINATION ${INCLUDE_INSTALL_DIR} ) #Get the include directory relative to CMAKECONFIG_INSTALL_DIR file(RELATIVE_PATH REL_INCLUDE_DIR "${CMAKECONFIG_INSTALL_DIR}" "${INCLUDE_INSTALL_DIR}") #Assemble the full relative path. This will be used in the LibkolabConfig.cmake, which will be installed in CMAKECONFIG_INSTALL_DIR set(CONF_INCLUDE_DIRS "\${Libkolab_CMAKE_DIR}/${REL_INCLUDE_DIR}") install(EXPORT LibkolabExport DESTINATION ${CMAKECONFIG_INSTALL_DIR} FILE LibkolabTargets.cmake) configure_file(${Libkolab_MODULE_DIR}/LibkolabConfig.cmake.in ${Libkolab_BINARY_DIR}/LibkolabConfig.cmake @ONLY) configure_file(${Libkolab_MODULE_DIR}/LibkolabConfigVersion.cmake.in ${Libkolab_BINARY_DIR}/LibkolabConfigVersion.cmake @ONLY) # Install these two files into the same directory as the generated exports-file. install(FILES ${Libkolab_BINARY_DIR}/LibkolabConfig.cmake ${Libkolab_BINARY_DIR}/LibkolabConfigVersion.cmake DESTINATION ${CMAKECONFIG_INSTALL_DIR}) include(SWIGUtils) if(PYTHON_BINDINGS) generatePythonBindings(shared shared.i) add_subdirectory(kolabformat/python) endif(PYTHON_BINDINGS) if(PHP_BINDINGS) generatePHPBindings(kolabshared shared.i) generatePHPBindings(dummy dummy.i) add_subdirectory(kolabformat/php) endif(PHP_BINDINGS) diff --git a/conversion/kcalconversion.cpp b/conversion/kcalconversion.cpp index 1f18290..0b3f6a6 100644 --- a/conversion/kcalconversion.cpp +++ b/conversion/kcalconversion.cpp @@ -1,865 +1,965 @@ /* * Copyright (C) 2011 Christian Mollekopf * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include "kcalconversion.h" #include #include #include #include #include #include #include #include "kolabformat/errorhandler.h" #include "commonconversion.h" namespace Kolab { namespace Conversion { //The uid of a contact which refers to the uuid of a contact in the addressbook #define CUSTOM_KOLAB_CONTACT_UUID "X_KOLAB_CONTACT_UUID" #define CUSTOM_KOLAB_CONTACT_CUTYPE "X_KOLAB_CONTACT_CUTYPE" #define CUSTOM_KOLAB_URL "X-KOLAB-URL" KCalCore::Duration toDuration(const Kolab::Duration &d) { int value = 0; if (d.hours() || d.minutes() || d.seconds()) { value = ((((d.weeks() * 7 + d.days()) * 24 + d.hours()) * 60 + d.minutes()) * 60 + d.seconds()); if (d.isNegative()) { value = -value; } return KCalCore::Duration(value); } value = d.weeks() * 7 + d.days(); if (d.isNegative()) { value = -value; } return KCalCore::Duration(value, KCalCore::Duration::Days); } Kolab::Duration fromDuration(const KCalCore::Duration &d) { int value = d.value(); bool isNegative = false; if (value < 0) { isNegative = true; value = -value; } //We don't know how the seconds/days were distributed before, so no point in distributing them (probably) if (d.isDaily()) { int days = value; return Kolab::Duration(days, 0, 0, 0, isNegative); } int seconds = value; // int minutes = seconds / 60; // seconds = seconds % 60; // int hours = minutes / 60; // minutes = minutes % 60; return Kolab::Duration(0, 0, 0, seconds, isNegative); } KCalCore::Incidence::Secrecy toSecrecy(Kolab::Classification c) { switch(c) { case Kolab::ClassPublic: return KCalCore::Incidence::SecrecyPublic; case Kolab::ClassPrivate: return KCalCore::Incidence::SecrecyPrivate; case Kolab::ClassConfidential: return KCalCore::Incidence::SecrecyConfidential; default: Error() << "unhandled"; Q_ASSERT(0); } return KCalCore::Incidence::SecrecyPublic; } Kolab::Classification fromSecrecy(KCalCore::Incidence::Secrecy c) { switch(c) { case KCalCore::Incidence::SecrecyPublic: return Kolab::ClassPublic; case KCalCore::Incidence::SecrecyPrivate: return Kolab::ClassPrivate; case KCalCore::Incidence::SecrecyConfidential: return Kolab::ClassConfidential; default: Error() << "unhandled"; Q_ASSERT(0); } return Kolab::ClassPublic; } int toPriority(int priority) { //Same mapping return priority; } int fromPriority(int priority) { //Same mapping return priority; } KCalCore::Incidence::Status toStatus(Kolab::Status s) { switch (s) { case StatusUndefined: return KCalCore::Incidence::StatusNone; case StatusNeedsAction: return KCalCore::Incidence::StatusNeedsAction; case StatusCompleted: return KCalCore::Incidence::StatusCompleted; case StatusInProcess: return KCalCore::Incidence::StatusInProcess; case StatusCancelled: return KCalCore::Incidence::StatusCanceled; case StatusTentative: return KCalCore::Incidence::StatusTentative; case StatusConfirmed: return KCalCore::Incidence::StatusConfirmed; case StatusDraft: return KCalCore::Incidence::StatusDraft; case StatusFinal: return KCalCore::Incidence::StatusFinal; default: Error() << "unhandled"; Q_ASSERT(0); } return KCalCore::Incidence::StatusNone; } Kolab::Status fromStatus(KCalCore::Incidence::Status s) { switch (s) { case KCalCore::Incidence::StatusNone: return StatusUndefined; case KCalCore::Incidence::StatusNeedsAction: return StatusNeedsAction; case KCalCore::Incidence::StatusCompleted: return StatusCompleted; case KCalCore::Incidence::StatusInProcess: return StatusInProcess; case KCalCore::Incidence::StatusCanceled: return StatusCancelled; case KCalCore::Incidence::StatusTentative: return StatusTentative; case KCalCore::Incidence::StatusConfirmed: return StatusConfirmed; case KCalCore::Incidence::StatusDraft: return StatusDraft; case KCalCore::Incidence::StatusFinal: return StatusFinal; default: Error() << "unhandled"; Q_ASSERT(0); } return StatusUndefined; } KCalCore::Attendee::PartStat toPartStat(Kolab::PartStatus p) { switch (p) { case PartNeedsAction: return KCalCore::Attendee::NeedsAction; case PartAccepted: return KCalCore::Attendee::Accepted; case PartDeclined: return KCalCore::Attendee::Declined; case PartTentative: return KCalCore::Attendee::Tentative; case PartDelegated: return KCalCore::Attendee::Delegated; default: Error() << "unhandled"; Q_ASSERT(0); } return KCalCore::Attendee::NeedsAction; } Kolab::PartStatus fromPartStat(KCalCore::Attendee::PartStat p) { switch (p) { case KCalCore::Attendee::NeedsAction: return PartNeedsAction; case KCalCore::Attendee::Accepted: return PartAccepted; case KCalCore::Attendee::Declined: return PartDeclined; case KCalCore::Attendee::Tentative: return PartTentative; case KCalCore::Attendee::Delegated: return PartDelegated; default: Error() << "unhandled"; Q_ASSERT(0); } return PartNeedsAction; } KCalCore::Attendee::Role toRole(Kolab::Role r) { switch (r) { case Required: return KCalCore::Attendee::ReqParticipant; case Chair: return KCalCore::Attendee::Chair; case Optional: return KCalCore::Attendee::OptParticipant; case NonParticipant: return KCalCore::Attendee::NonParticipant; default: Error() << "unhandled"; Q_ASSERT(0); } return KCalCore::Attendee::ReqParticipant; } Kolab::Role fromRole(KCalCore::Attendee::Role r) { switch (r) { case KCalCore::Attendee::ReqParticipant: return Required; case KCalCore::Attendee::Chair: return Chair; case KCalCore::Attendee::OptParticipant: return Optional; case KCalCore::Attendee::NonParticipant: return NonParticipant; default: Error() << "unhandled"; Q_ASSERT(0); } return Required; } template QString getCustomProperty(const QString &id, const T &e) { std::vector &props = e.customProperties(); foreach (const CustomProperty &p, props) { if (fromStdString(p.identifier) == id) { return fromStdString(p.value); } } } template void setIncidence(KCalCore::Incidence &i, const T &e) { if (!e.uid().empty()) { i.setUid(fromStdString(e.uid())); } i.setCreated(toDate(e.created())); i.setLastModified(toDate(e.lastModified())); i.setRevision(e.sequence()); i.setSecrecy(toSecrecy(e.classification())); i.setCategories(toStringList(e.categories())); if (e.start().isValid()) { i.setDtStart(toDate(e.start())); if (e.start().isDateOnly()) { i.setAllDay(true); } } i.setSummary(fromStdString(e.summary())); //TODO detect richtext i.setDescription(fromStdString(e.description())); //TODO detect richtext i.setStatus(toStatus(e.status())); foreach (const Kolab::Attendee a, e.attendees()) { //FIXME percent encoding? /* * KCalCore always sets a UID if empty, but that's just a pointer, and not the uid of a real contact. * Since that means the semantics of the two are different, we have to store the kolab uid as a custom property. */ // QUrl::fromPercentEncoding( +#ifdef LEGACY_KCALCORE + KCalCore::Attendee::Ptr attendee = KCalCore::Attendee::Ptr(new KCalCore::Attendee(fromStdString(a.contact().name()), + fromStdString(a.contact().email()), + a.rsvp(), + toPartStat(a.partStat()), + toRole(a.role()) )); + if (!a.contact().uid().empty()) { //TODO Identify contact from addressbook based on uid + attendee->customProperties().setNonKDECustomProperty(CUSTOM_KOLAB_CONTACT_UUID, fromStdString(a.contact().uid())); + } + if (!a.delegatedTo().empty()) { + if (a.delegatedTo().size() > 1) { + WARNING("multiple delegatees are not supported"); + } + + attendee->setDelegate(toMailto(a.delegatedTo().front().email(), a.delegatedTo().front().name()).toString()); + } + if (!a.delegatedFrom().empty()) { + if (a.delegatedFrom().size() > 1) { + WARNING("multiple delegators are not supported"); + } + attendee->setDelegator(toMailto(a.delegatedFrom().front().email(), a.delegatedFrom().front().name()).toString()); + } + if (a.cutype() != CutypeIndividual) { + attendee->customProperties().setNonKDECustomProperty(CUSTOM_KOLAB_CONTACT_CUTYPE, QString::number(a.cutype())); + } + i.addAttendee(attendee); +#else KCalCore::Attendee attendee(fromStdString(a.contact().name()), fromStdString(a.contact().email()), a.rsvp(), toPartStat(a.partStat()), toRole(a.role()) ); if (!a.contact().uid().empty()) { //TODO Identify contact from addressbook based on uid attendee.customProperties().setNonKDECustomProperty(CUSTOM_KOLAB_CONTACT_UUID, fromStdString(a.contact().uid())); } if (!a.delegatedTo().empty()) { if (a.delegatedTo().size() > 1) { WARNING("multiple delegatees are not supported"); } attendee.setDelegate(toMailto(a.delegatedTo().front().email(), a.delegatedTo().front().name()).toString()); } if (!a.delegatedFrom().empty()) { if (a.delegatedFrom().size() > 1) { WARNING("multiple delegators are not supported"); } attendee.setDelegator(toMailto(a.delegatedFrom().front().email(), a.delegatedFrom().front().name()).toString()); } if (a.cutype() != CutypeIndividual) { attendee.customProperties().setNonKDECustomProperty(CUSTOM_KOLAB_CONTACT_CUTYPE, QString::number(a.cutype())); } i.addAttendee(attendee); +#endif } foreach (const Kolab::Attachment a, e.attachments()) { +#ifdef LEGACY_KCALCORE + KCalCore::Attachment::Ptr ptr; + if (!a.uri().empty()) { + ptr = KCalCore::Attachment::Ptr(new KCalCore::Attachment(fromStdString(a.uri()), fromStdString(a.mimetype()))); + } else { + ptr = KCalCore::Attachment::Ptr(new KCalCore::Attachment(QByteArray::fromRawData(a.data().c_str(), a.data().size()).toBase64(), fromStdString(a.mimetype()))); + } + if (!a.label().empty()) { + ptr->setLabel(fromStdString(a.label())); + } + i.addAttachment(ptr); +#else KCalCore::Attachment ptr; if (!a.uri().empty()) { ptr = KCalCore::Attachment(fromStdString(a.uri()), fromStdString(a.mimetype())); } else { ptr = KCalCore::Attachment(QByteArray::fromRawData(a.data().c_str(), a.data().size()).toBase64(), fromStdString(a.mimetype())); } if (!a.label().empty()) { ptr.setLabel(fromStdString(a.label())); } i.addAttachment(ptr); +#endif } QMap props; foreach (const Kolab::CustomProperty &prop, e.customProperties()) { QString key; if (prop.identifier.compare(0, 5, "X-KDE")) { key.append(QString::fromLatin1("X-KOLAB-")); } key.append(fromStdString(prop.identifier)); props.insert(key.toLatin1(), fromStdString(prop.value)); // i.setCustomProperty("KOLAB", fromStdString(prop.identifier).toLatin1(), fromStdString(prop.value)); } i.setCustomProperties(props); } template void getIncidence(T &i, const I &e) { i.setUid(toStdString(e.uid())); i.setCreated(fromDate(e.created())); i.setLastModified(fromDate(e.lastModified())); i.setSequence(e.revision()); i.setClassification(fromSecrecy(e.secrecy())); i.setCategories(fromStringList(e.categories())); i.setStart(fromDate(e.dtStart())); i.setSummary(toStdString(e.summary())); i.setDescription(toStdString(e.description())); i.setStatus(fromStatus(e.status())); std::vector attendees; +#ifdef LEGACY_KCALCORE + foreach (const KCalCore::Attendee::Ptr attendee, e.attendees()) { + const QString &uid = attendee->customProperties().nonKDECustomProperty(CUSTOM_KOLAB_CONTACT_UUID); + Kolab::Attendee a(Kolab::ContactReference(toStdString(attendee->email()), toStdString(attendee->name()), toStdString(uid))); + a.setRSVP(attendee->RSVP()); + a.setPartStat(fromPartStat(attendee->status())); + a.setRole(fromRole(attendee->role())); + if (!attendee->delegate().isEmpty()) { + std::string name; + const std::string &email = fromMailto(QUrl(attendee->delegate()), name); + a.setDelegatedTo(std::vector() << Kolab::ContactReference(email, name)); + } + if (!attendee->delegator().isEmpty()) { + std::string name; + const std::string &email = fromMailto(QUrl(attendee->delegator()), name); + a.setDelegatedFrom(std::vector() << Kolab::ContactReference(email, name)); + } + const QString &cutype = attendee->customProperties().nonKDECustomProperty(CUSTOM_KOLAB_CONTACT_CUTYPE); + if (!cutype.isEmpty()) { + a.setCutype(static_cast(cutype.toInt())); + } + + attendees.push_back(a); + } +#else foreach (const KCalCore::Attendee attendee, e.attendees()) { const QString &uid = attendee.customProperties().nonKDECustomProperty(CUSTOM_KOLAB_CONTACT_UUID); Kolab::Attendee a(Kolab::ContactReference(toStdString(attendee.email()), toStdString(attendee.name()), toStdString(uid))); a.setRSVP(attendee.RSVP()); a.setPartStat(fromPartStat(attendee.status())); a.setRole(fromRole(attendee.role())); if (!attendee.delegate().isEmpty()) { std::string name; const std::string &email = fromMailto(QUrl(attendee.delegate()), name); a.setDelegatedTo(std::vector() << Kolab::ContactReference(email, name)); } if (!attendee.delegator().isEmpty()) { std::string name; const std::string &email = fromMailto(QUrl(attendee.delegator()), name); a.setDelegatedFrom(std::vector() << Kolab::ContactReference(email, name)); } const QString &cutype = attendee.customProperties().nonKDECustomProperty(CUSTOM_KOLAB_CONTACT_CUTYPE); if (!cutype.isEmpty()) { a.setCutype(static_cast(cutype.toInt())); } attendees.push_back(a); } +#endif i.setAttendees(attendees); std::vector attachments; +#ifdef LEGACY_KCALCORE + foreach (const KCalCore::Attachment::Ptr &ptr, e.attachments()) { + Kolab::Attachment a; + if (ptr->isUri()) { + a.setUri(toStdString(ptr->uri()), toStdString(ptr->mimeType())); + } else { + a.setData(std::string(ptr->decodedData().data(), ptr->decodedData().size()), toStdString(ptr->mimeType())); + } + a.setLabel(toStdString(ptr->label())); + attachments.push_back(a); + } +#else foreach (const KCalCore::Attachment &ptr, e.attachments()) { Kolab::Attachment a; if (ptr.isUri()) { a.setUri(toStdString(ptr.uri()), toStdString(ptr.mimeType())); } else { a.setData(std::string(ptr.decodedData().data(), ptr.decodedData().size()), toStdString(ptr.mimeType())); } a.setLabel(toStdString(ptr.label())); attachments.push_back(a); } +#endif i.setAttachments(attachments); std::vector customProperties; const QMap &props = e.customProperties(); for (QMap::const_iterator it = props.begin(); it != props.end(); it++) { QString key(it.key()); if (key == QLatin1String(CUSTOM_KOLAB_URL)) { continue; } customProperties.push_back(Kolab::CustomProperty(toStdString(key.remove("X-KOLAB-")), toStdString(it.value()))); } i.setCustomProperties(customProperties); } int toWeekDay(Kolab::Weekday wday) { switch (wday) { case Kolab::Monday: return 1; case Kolab::Tuesday: return 2; case Kolab::Wednesday: return 3; case Kolab::Thursday: return 4; case Kolab::Friday: return 5; case Kolab::Saturday: return 6; case Kolab::Sunday: return 7; default: Error() << "unhandled"; Q_ASSERT(0); } return 1; } Kolab::Weekday fromWeekDay(int wday) { switch (wday) { case 1: return Kolab::Monday; case 2: return Kolab::Tuesday; case 3: return Kolab::Wednesday; case 4: return Kolab::Thursday; case 5: return Kolab::Friday; case 6: return Kolab::Saturday; case 7: return Kolab::Sunday; default: Error() << "unhandled"; Q_ASSERT(0); } return Kolab::Monday; } KCalCore::RecurrenceRule::PeriodType toRecurrenceType(Kolab::RecurrenceRule::Frequency freq) { switch(freq) { case Kolab::RecurrenceRule::FreqNone: Warning() << "no recurrence?"; break; case Kolab::RecurrenceRule::Yearly: return KCalCore::RecurrenceRule::rYearly; case Kolab::RecurrenceRule::Monthly: return KCalCore::RecurrenceRule::rMonthly; case Kolab::RecurrenceRule::Weekly: return KCalCore::RecurrenceRule::rWeekly; case Kolab::RecurrenceRule::Daily: return KCalCore::RecurrenceRule::rDaily; case Kolab::RecurrenceRule::Hourly: return KCalCore::RecurrenceRule::rHourly; case Kolab::RecurrenceRule::Minutely: return KCalCore::RecurrenceRule::rMinutely; case Kolab::RecurrenceRule::Secondly: return KCalCore::RecurrenceRule::rSecondly; default: Error() << "unhandled"; Q_ASSERT(0); } return KCalCore::RecurrenceRule::rNone; } Kolab::RecurrenceRule::Frequency fromRecurrenceType(KCalCore::RecurrenceRule::PeriodType freq) { switch(freq) { case KCalCore::RecurrenceRule::rNone: Warning() << "no recurrence?"; break; case KCalCore::RecurrenceRule::rYearly: return Kolab::RecurrenceRule::Yearly; case KCalCore::RecurrenceRule::rMonthly: return Kolab::RecurrenceRule::Monthly; case KCalCore::RecurrenceRule::rWeekly: return Kolab::RecurrenceRule::Weekly; case KCalCore::RecurrenceRule::rDaily: return Kolab::RecurrenceRule::Daily; case KCalCore::RecurrenceRule::rHourly: return Kolab::RecurrenceRule::Hourly; case KCalCore::RecurrenceRule::rMinutely: return Kolab::RecurrenceRule::Minutely; case KCalCore::RecurrenceRule::rSecondly: return Kolab::RecurrenceRule::Secondly; default: Error() << "unhandled"; Q_ASSERT(0); } return Kolab::RecurrenceRule::FreqNone; } KCalCore::RecurrenceRule::WDayPos toWeekDayPos(const Kolab::DayPos &dp) { return KCalCore::RecurrenceRule::WDayPos(dp.occurence(), toWeekDay(dp.weekday())); } Kolab::DayPos fromWeekDayPos(const KCalCore::RecurrenceRule::WDayPos &dp) { return Kolab::DayPos(dp.pos(), fromWeekDay(dp.day())); } template void setRecurrence(KCalCore::Incidence &e, const T &event) { const Kolab::RecurrenceRule &rrule = event.recurrenceRule(); if (rrule.isValid()) { KCalCore::Recurrence *rec = e.recurrence(); KCalCore::RecurrenceRule *defaultRR = rec->defaultRRule(true); Q_ASSERT(defaultRR); defaultRR->setWeekStart(toWeekDay(rrule.weekStart())); defaultRR->setRecurrenceType(toRecurrenceType(rrule.frequency())); defaultRR->setFrequency(rrule.interval()); if (rrule.end().isValid()) { rec->setEndDateTime(toDate(rrule.end())); //TODO date/datetime setEndDate(). With date-only the start date has to be taken into account. } else { rec->setDuration(rrule.count()); } if (!rrule.bysecond().empty()) { defaultRR->setBySeconds(QVector::fromStdVector(rrule.bysecond()).toList()); } if (!rrule.byminute().empty()) { defaultRR->setByMinutes(QVector::fromStdVector(rrule.byminute()).toList()); } if (!rrule.byhour().empty()) { defaultRR->setByHours(QVector::fromStdVector(rrule.byhour()).toList()); } if (!rrule.byday().empty()) { QList daypos; foreach(const Kolab::DayPos &dp, rrule.byday()) { daypos.append(toWeekDayPos(dp)); } defaultRR->setByDays(daypos); } if (!rrule.bymonthday().empty()) { defaultRR->setByMonthDays(QVector::fromStdVector(rrule.bymonthday()).toList()); } if (!rrule.byyearday().empty()) { defaultRR->setByYearDays(QVector::fromStdVector(rrule.byyearday()).toList()); } if (!rrule.byweekno().empty()) { defaultRR->setByWeekNumbers(QVector::fromStdVector(rrule.byweekno()).toList()); } if (!rrule.bymonth().empty()) { defaultRR->setByMonths(QVector::fromStdVector(rrule.bymonth()).toList()); } } foreach (const Kolab::cDateTime &dt, event.recurrenceDates()) { if (dt.isDateOnly()) { e.recurrence()->addRDate(toDate(dt).date()); } else { e.recurrence()->addRDateTime(toDate(dt)); } } foreach (const Kolab::cDateTime &dt, event.exceptionDates()) { if (dt.isDateOnly()) { e.recurrence()->addExDate(toDate(dt).date()); } else { e.recurrence()->addExDateTime(toDate(dt)); } } } template void getRecurrence(T &i, const I &e) { if (!e.recurs()) { return; } KCalCore::Recurrence *rec = e.recurrence(); KCalCore::RecurrenceRule *defaultRR = rec->defaultRRule(false); if (!defaultRR) { Warning() << "no recurrence"; return; } Q_ASSERT(defaultRR); Kolab::RecurrenceRule rrule; rrule.setWeekStart(fromWeekDay(defaultRR->weekStart())); rrule.setFrequency(fromRecurrenceType(defaultRR->recurrenceType())); rrule.setInterval(defaultRR->frequency()); if (defaultRR->duration() != 0) { //Inidcates if end date is set or not if (defaultRR->duration() > 0) { rrule.setCount(defaultRR->duration()); } } else { rrule.setEnd(fromDate(defaultRR->endDt())); } rrule.setBysecond(defaultRR->bySeconds().toVector().toStdVector()); rrule.setByminute(defaultRR->byMinutes().toVector().toStdVector()); rrule.setByhour(defaultRR->byHours().toVector().toStdVector()); std::vector daypos; foreach (const KCalCore::RecurrenceRule::WDayPos &dp, defaultRR->byDays()) { daypos.push_back(fromWeekDayPos(dp)); } rrule.setByday(daypos); rrule.setBymonthday(defaultRR->byMonthDays().toVector().toStdVector()); rrule.setByyearday(defaultRR->byYearDays().toVector().toStdVector()); rrule.setByweekno(defaultRR->byWeekNumbers().toVector().toStdVector()); rrule.setBymonth(defaultRR->byMonths().toVector().toStdVector()); i.setRecurrenceRule(rrule); std::vector rdates; foreach (const QDateTime &dt, rec->rDateTimes()) { rdates.push_back(fromDate(dt)); } foreach (const QDate &dt, rec->rDates()) { rdates.push_back(fromDate(QDateTime(dt))); } i.setRecurrenceDates(rdates); std::vector exdates; foreach (const QDateTime &dt, rec->exDateTimes()) { exdates.push_back(fromDate(dt)); } foreach (const QDate &dt, rec->exDates()) { exdates.push_back(fromDate(QDateTime(dt))); } i.setExceptionDates(exdates); if (!rec->exRules().empty()) { Warning() << "exrules are not supported"; } } template void setTodoEvent(KCalCore::Incidence &i, const T &e) { i.setPriority(toPriority(e.priority())); if (!e.location().empty()) { i.setLocation(fromStdString(e.location())); //TODO detect richtext } if (e.organizer().isValid()) { +#ifdef LEGACY_KCALCORE + i.setOrganizer(KCalCore::Person::Ptr(new KCalCore::Person(fromStdString(e.organizer().name()), fromStdString(e.organizer().email())))); //TODO handle uid too +#else i.setOrganizer(KCalCore::Person(fromStdString(e.organizer().name()), fromStdString(e.organizer().email()))); //TODO handle uid too +#endif } if (!e.url().empty()) { i.setNonKDECustomProperty(CUSTOM_KOLAB_URL, fromStdString(e.url())); } if (e.recurrenceID().isValid()) { i.setRecurrenceId(toDate(e.recurrenceID())); i.setThisAndFuture(e.thisAndFuture()); } setRecurrence(i, e); foreach (const Kolab::Alarm a, e.alarms()) { KCalCore::Alarm::Ptr alarm = KCalCore::Alarm::Ptr(new KCalCore::Alarm(&i)); switch (a.type()) { case Kolab::Alarm::EMailAlarm: { KCalCore::Person::List receipents; foreach (Kolab::ContactReference c ,a.attendees()) { +#ifdef LEGACY_KCALCORE + KCalCore::Person::Ptr person = KCalCore::Person::Ptr(new KCalCore::Person(fromStdString(c.name()), fromStdString(c.email()))); +#else KCalCore::Person person(fromStdString(c.name()), fromStdString(c.email())); +#endif receipents.append(person); } alarm->setEmailAlarm(fromStdString(a.summary()), fromStdString(a.description()), receipents); } break; case Kolab::Alarm::DisplayAlarm: alarm->setDisplayAlarm(fromStdString(a.text())); break; case Kolab::Alarm::AudioAlarm: alarm->setAudioAlarm(fromStdString(a.audioFile().uri())); break; default: Error() << "invalid alarm"; } if (a.start().isValid()) { alarm->setTime(toDate(a.start())); } else if (a.relativeStart().isValid()) { if (a.relativeTo() == Kolab::End) { alarm->setEndOffset(toDuration(a.relativeStart())); } else { alarm->setStartOffset(toDuration(a.relativeStart())); } } alarm->setSnoozeTime(toDuration(a.duration())); alarm->setRepeatCount(a.numrepeat()); alarm->setEnabled(true); i.addAlarm(alarm); } } template void getTodoEvent(T &i, const I &e) { i.setPriority(fromPriority(e.priority())); i.setLocation(toStdString(e.location())); +#ifdef LEGACY_KCALCORE + if (!e.organizer()->email().isEmpty()) { + i.setOrganizer(Kolab::ContactReference(Kolab::ContactReference::EmailReference, toStdString(e.organizer()->email()), toStdString(e.organizer()->name()))); //TODO handle uid too + } +#else if (!e.organizer().email().isEmpty()) { i.setOrganizer(Kolab::ContactReference(Kolab::ContactReference::EmailReference, toStdString(e.organizer().email()), toStdString(e.organizer().name()))); //TODO handle uid too } +#endif i.setUrl(toStdString(e.nonKDECustomProperty(CUSTOM_KOLAB_URL))); i.setRecurrenceID(fromDate(e.recurrenceId()), e.thisAndFuture()); getRecurrence(i, e); std::vector alarms; foreach (const KCalCore::Alarm::Ptr &a, e.alarms()) { Kolab::Alarm alarm; //TODO KCalCore disables alarms using KCalCore::Alarm::enabled() (X-KDE-KCALCORE-ENABLED) We should either delete the alarm, or store the attribute . //Ideally we would store the alarm somewhere and temporarily delete it, so we can restore it when parsing. For now we just remove disabled alarms. if (!a->enabled()) { Warning() << "skipping disabled alarm"; continue; } switch (a->type()) { case KCalCore::Alarm::Display: alarm = Kolab::Alarm(toStdString(a->text())); break; case KCalCore::Alarm::Email: { std::vector receipents; +#ifdef LEGACY_KCALCORE + foreach(const KCalCore::Person::Ptr &p, a->mailAddresses()) { + receipents.push_back(Kolab::ContactReference(toStdString(p->email()), toStdString(p->name()))); + } +#else foreach(const KCalCore::Person &p, a->mailAddresses()) { receipents.push_back(Kolab::ContactReference(toStdString(p.email()), toStdString(p.name()))); } +#endif alarm = Kolab::Alarm(toStdString(a->mailSubject()), toStdString(a->mailText()), receipents); } break; case KCalCore::Alarm::Audio: { Kolab::Attachment audioFile; audioFile.setUri(toStdString(a->audioFile()), std::string()); alarm = Kolab::Alarm(audioFile); } break; default: Error() << "unhandled alarm"; } if (a->hasTime()) { alarm.setStart(fromDate(a->time())); } else if (a->hasStartOffset()) { alarm.setRelativeStart(fromDuration(a->startOffset()), Start); } else if (a->hasEndOffset()) { alarm.setRelativeStart(fromDuration(a->endOffset()), End); } else { Error() << "alarm trigger is missing"; continue; } alarm.setDuration(fromDuration(a->snoozeTime()), a->repeatCount()); alarms.push_back(alarm); } i.setAlarms(alarms); } KCalCore::Event::Ptr toKCalCore(const Kolab::Event &event) { KCalCore::Event::Ptr e(new KCalCore::Event); setIncidence(*e, event); setTodoEvent(*e, event); if (event.end().isValid()) { e->setDtEnd(toDate(event.end())); } if (event.duration().isValid()) { e->setDuration(toDuration(event.duration())); } if (event.transparency()) { e->setTransparency(KCalCore::Event::Transparent); } else { e->setTransparency(KCalCore::Event::Opaque); } return e; } Event fromKCalCore(const KCalCore::Event &event) { Event e; getIncidence(e, event); getTodoEvent(e, event); if (event.hasEndDate()) { e.setEnd(fromDate(event.dtEnd())); } else if (event.hasDuration()) { e.setDuration(fromDuration(event.duration())); } if (event.transparency() == KCalCore::Event::Transparent) { e.setTransparency(true); } else { e.setTransparency(false); } return e; } KCalCore::Todo::Ptr toKCalCore ( const Todo &todo ) { KCalCore::Todo::Ptr e(new KCalCore::Todo); setIncidence(*e, todo); setTodoEvent(*e, todo); if (todo.due().isValid()) { e->setDtDue(toDate(todo.due())); } if (!todo.relatedTo().empty()) { e->setRelatedTo(Conversion::fromStdString(todo.relatedTo().front()), KCalCore::Incidence::RelTypeParent); if (todo.relatedTo().size() > 1) { Error() << "only one relation support but got multiple"; } } e->setPercentComplete(todo.percentComplete()); return e; } Todo fromKCalCore ( const KCalCore::Todo &todo ) { Todo t; getIncidence(t, todo); getTodoEvent(t, todo); t.setDue(fromDate(todo.dtDue(true))); t.setPercentComplete(todo.percentComplete()); const QString relatedTo = todo.relatedTo(KCalCore::Incidence::RelTypeParent); if (!relatedTo.isEmpty()) { std::vector relateds; relateds.push_back(Conversion::toStdString(relatedTo)); t.setRelatedTo(relateds); } return t; } KCalCore::Journal::Ptr toKCalCore ( const Journal &journal ) { KCalCore::Journal::Ptr e(new KCalCore::Journal); setIncidence(*e, journal); //TODO contacts return e; } Journal fromKCalCore ( const KCalCore::Journal &journal ) { Journal j; getIncidence(j, journal); //TODO contacts return j; } } } diff --git a/tests/kcalconversiontest.cpp b/tests/kcalconversiontest.cpp index b0ff3e5..7644b6e 100644 --- a/tests/kcalconversiontest.cpp +++ b/tests/kcalconversiontest.cpp @@ -1,526 +1,536 @@ /* * Copyright (C) 2012 Christian Mollekopf * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include "kcalconversiontest.h" #include #include #include #include #include #include "conversion/kcalconversion.h" #include "conversion/kcalconversion.cpp" #include "testhelpers.h" using namespace Kolab::Conversion; template void compareVectors(const QVector &list, const QVector &other) { QCOMPARE(list.size(), other.size()); for (int i = 0 ; i < list.size(); i++) { QCOMPARE(list.at(i), other.at(i)); } } template void comparePointerVectors(const QVector &list, const QVector &other) { QCOMPARE(list.size(), other.size()); for (int i = 0 ; i < list.size(); i++) { QCOMPARE(*list.at(i), *other.at(i)); } } void compareAttendeesVectors(const KCalCore::Attendee::List &list, const KCalCore::Attendee::List &other) { QCOMPARE(list.size(), other.size()); +#ifndef LEGACY_KCALCORE for (int i = 0 ; i < list.size(); i++) { KCalCore::Attendee at1 = list.at(i); at1.setUid(QString()); KCalCore::Attendee at2 = other.at(i); at2.setUid(QString()); QCOMPARE(at1, at2); } +#endif } void KCalConversionTest::initTestCase() { } void KCalConversionTest::testDate_data() { QTest::addColumn( "input" ); QTest::addColumn( "result" ); QTest::newRow( "datetime with tz" ) << Kolab::cDateTime("Europe/Zurich",2006,1,8,12,0,0) << QDateTime(QDate(2006, 1, 8), QTime(12, 0, 0), QTimeZone("Europe/Zurich")); QTest::newRow( "floating datetime" ) << Kolab::cDateTime(2006,1,8,12,0,0, false) << QDateTime(QDate(2006, 1, 8), QTime(12, 0, 0), Qt::LocalTime); QTest::newRow( "utc datetime" ) << Kolab::cDateTime(2006,1,8,12,0,0, true) << QDateTime(QDateTime(QDate(2006, 1, 8), QTime(12, 0, 0), Qt::UTC)); QTest::newRow( "date only" ) << Kolab::cDateTime(2006,1,8, 0, 0, 0) << QDateTime(QDate(2006, 1, 8)); } void KCalConversionTest::testDate() { QFETCH(Kolab::cDateTime, input); QFETCH(QDateTime, result); qWarning() << "expected result" << result; const QDateTime &r = Kolab::Conversion::toDate(input); QCOMPARE(r, result); qWarning() << "toDate" << r; const Kolab::cDateTime &r2 = Kolab::Conversion::fromDate(result); QCOMPARE(r2, input); } void KCalConversionTest::testDuration_data() { QTest::addColumn( "input" ); QTest::addColumn( "result" ); QTest::addColumn( "fromResult" ); QTest::newRow( "seconds" ) << Kolab::Duration(0,0,0,30,false) << KCalCore::Duration(30, KCalCore::Duration::Seconds) << Kolab::Duration(0,0,0,30,false); QTest::newRow( "minutes" ) << Kolab::Duration(0,0,1,30,false) << KCalCore::Duration(90, KCalCore::Duration::Seconds) << Kolab::Duration(0,0,0,90,false); QTest::newRow( "hours" ) << Kolab::Duration(0,1,1,30,false) << KCalCore::Duration(60*60+90, KCalCore::Duration::Seconds) << Kolab::Duration(0,0,0,60*60+90,false); QTest::newRow( "days" ) << Kolab::Duration(1,1,1,30,false) << KCalCore::Duration(24*60*60+60*60+90, KCalCore::Duration::Seconds) << Kolab::Duration(0,0,0,24*60*60+60*60+90,false); QTest::newRow( "daysonly" ) << Kolab::Duration(30,0,0,0, false) << KCalCore::Duration(30, KCalCore::Duration::Days) << Kolab::Duration(30,0,0,0,false); QTest::newRow( "weeks" ) << Kolab::Duration(30,false) << KCalCore::Duration(30*7, KCalCore::Duration::Days) << Kolab::Duration(30*7,0,0,0,false); } void KCalConversionTest::testDuration() { QFETCH(Kolab::Duration, input); QFETCH(KCalCore::Duration, result); QFETCH(Kolab::Duration, fromResult); const KCalCore::Duration &r = Kolab::Conversion::toDuration(input); QCOMPARE(r, result); const Kolab::Duration &r2 = Kolab::Conversion::fromDuration(result); QCOMPARE(r2, fromResult); } void KCalConversionTest::testDateTZ_data() { QTest::addColumn( "input" ); QTest::addColumn( "result" ); QTest::newRow( "berlin" ) << Kolab::cDateTime("Europe/Berlin",2006,1,8,12,0,0) << QDateTime(QDate(2006, 1, 8), QTime(12, 0, 0), QTimeZone("Europe/Berlin")); } void KCalConversionTest::testDateTZ() { QFETCH(Kolab::cDateTime, input); QFETCH(QDateTime, result); const QDateTime &r = Kolab::Conversion::toDate(input); //FIXME QCOMPARE(result.timeZone().id(), QString::fromStdString(input.timezone()).toLatin1()); // QCOMPARE(r.timeZone().currentOffset(), result.timeZone().currentOffset()); // const Kolab::cDateTime &r2 = Kolab::Conversion::fromDate(result); // QCOMPARE(QString::fromStdString(r2.timezone()), result.timeZone().name()); } void KCalConversionTest::testConversion_data() { QTest::addColumn( "kcal" ); QTest::addColumn( "kolab" ); Kolab::cDateTime date(2011,2,2,12,11,10,true); Kolab::cDateTime date2(2011,2,2,12,12,10,true); Kolab::cDateTime date3(2012,2,2,12,12,10,true); std::vector intVector; intVector.push_back(1); intVector.push_back(-3); intVector.push_back(2); std::vector stringVector; stringVector.push_back("cat1"); stringVector.push_back("cat2"); stringVector.push_back("parent/child"); { KCalCore::Event kcal; kcal.setUid("uid"); kcal.setCreated(toDate(date)); kcal.setLastModified(toDate(date)); kcal.setRevision(3); kcal.setSecrecy(KCalCore::Incidence::SecrecyConfidential); kcal.setCategories(toStringList(stringVector)); kcal.setDtStart(toDate(date)); kcal.setDtEnd(toDate(date2)); kcal.setTransparency(KCalCore::Event::Transparent); kcal.setRecurrenceId(toDate(date2)); kcal.recurrence()->setDaily(3); kcal.recurrence()->setDuration(5); kcal.recurrence()->addRDateTime(toDate(date2)); kcal.recurrence()->addRDate(toDate(date2).date()); kcal.recurrence()->addExDateTime(toDate(date3)); kcal.recurrence()->addExDate(toDate(date3).date()); KCalCore::RecurrenceRule *rr = kcal.recurrence()->defaultRRule(true); QList intList = QVector::fromStdVector(intVector).toList(); rr->setBySeconds(intList); rr->setByMinutes(intList); rr->setByHours(intList); rr->setByDays(QList() << KCalCore::RecurrenceRule::WDayPos(3,1) << KCalCore::RecurrenceRule::WDayPos(5,4)); rr->setByMonthDays(intList); rr->setByYearDays(intList); rr->setByMonths(intList); rr->setByWeekNumbers(intList); kcal.setSummary("summary"); kcal.setDescription("description"); kcal.setPriority(3); kcal.setStatus(KCalCore::Incidence::StatusConfirmed); kcal.setLocation("location"); +#ifndef LEGACY_KCALCORE kcal.setOrganizer(KCalCore::Person("organizer", "organizer@email")); +#endif //Url kcal.setNonKDECustomProperty("X-KOLAB-URL", "http://test.org"); +#ifndef LEGACY_KCALCORE KCalCore::Attendee att("attendee", "attendee@email", false, KCalCore::Attendee::NeedsAction, KCalCore::Attendee::ReqParticipant); att.setDelegate("mailto:delegatee"); att.setDelegator("mailto:delegator"); kcal.addAttendee(att); kcal.addAttachment(KCalCore::Attachment(QString("uri"), "mimetype/mime")); +#endif +#ifndef LEGACY_KCALCORE KCalCore::Alarm::Ptr alarm = KCalCore::Alarm::Ptr(new KCalCore::Alarm(&kcal)); KCalCore::Person::List addressees; addressees.append(KCalCore::Person("name", "email@email")); alarm->setEmailAlarm("subject", "text", addressees, QStringList()); //No support for attachments kcal.addAlarm(alarm); +#endif //TODO alarms kcal.setNonKDECustomProperty("X-KOLAB-key1", "value1"); kcal.setNonKDECustomProperty("X-KOLAB-key2", "value2"); kcal.setCustomProperty("SOMEOTHERAPP", "key2", "value2"); Q_ASSERT(kcal.nonKDECustomProperty("X-KOLAB-key1") == "value1"); Kolab::Event kolab; kolab.setUid("uid"); kolab.setCreated(date); kolab.setLastModified(date); kolab.setSequence(3); kolab.setClassification(Kolab::ClassConfidential); kolab.setCategories(stringVector); kolab.setStart(date); kolab.setEnd(date2); kolab.setTransparency(true); Kolab::RecurrenceRule rrule; rrule.setInterval(3); rrule.setFrequency(Kolab::RecurrenceRule::Daily); rrule.setCount(5); rrule.setBysecond(intVector); rrule.setByminute(intVector); rrule.setByhour(intVector); rrule.setByday(std::vector() << Kolab::DayPos(3, Kolab::Monday) << Kolab::DayPos(5, Kolab::Thursday)); rrule.setBymonthday(intVector); rrule.setByyearday(intVector); rrule.setByweekno(intVector); rrule.setBymonth(intVector); kolab.setRecurrenceRule(rrule); kolab.setRecurrenceID(date2, false); kolab.setRecurrenceDates(std::vector() << date2 << Kolab::cDateTime(date2.year(), date2.month(), date2.day())); kolab.setExceptionDates(std::vector() << date3 << Kolab::cDateTime(date3.year(), date3.month(), date3.day())); kolab.setSummary("summary"); kolab.setDescription("description"); kolab.setPriority(3); kolab.setStatus(Kolab::StatusConfirmed); kolab.setLocation("location"); kolab.setOrganizer(Kolab::ContactReference(Kolab::ContactReference::EmailReference,"organizer@email", "organizer")); //TODO uid kolab.setUrl("http://test.org"); Kolab::Attendee a(Kolab::ContactReference(Kolab::ContactReference::EmailReference,"attendee@email", "attendee"));//TODO uid a.setDelegatedTo(std::vector() << Kolab::ContactReference(Kolab::ContactReference::EmailReference,"delegatee@email", "delegatee")); a.setDelegatedFrom(std::vector() << Kolab::ContactReference(Kolab::ContactReference::EmailReference,"delegator@email", "delegator")); a.setCutype(Kolab::CutypeIndividual); kolab.setAttendees(std::vector() << a); Kolab::Attachment attach; attach.setUri("uri", "mimetype/mime"); kolab.setAttachments(std::vector() << attach); // std::vector receipents; // receipents.push_back("email@email"); // Kolab::Alarm alarm2("summary", "description", receipents); // kolab.setAlarms(std::vector() << alarm2); //The sorting is random, just sort them here how we think they should arrive so we don't have to sort during compare (due to lazyness). std::vector customproperties; customproperties.push_back(Kolab::CustomProperty("X-KDE-SOMEOTHERAPP-key2", "value2")); customproperties.push_back(Kolab::CustomProperty("key1", "value1")); customproperties.push_back(Kolab::CustomProperty("key2", "value2")); kolab.setCustomProperties(customproperties); QTest::newRow( "with endDate and recurrence duration" ) << kcal << kolab; } { KCalCore::Event kcal; kcal.setUid("uid"); kcal.setCreated(toDate(date)); kcal.setLastModified(toDate(date)); kcal.setRevision(3); kcal.setDtStart(toDate(date)); kcal.setDuration(KCalCore::Duration(toDate(date), toDate(date2))); kcal.recurrence()->setDaily(3); kcal.recurrence()->setEndDateTime(toDate(date3)); Kolab::Event kolab; kolab.setUid("uid"); kolab.setCreated(date); kolab.setLastModified(date); kolab.setSequence(3); kolab.setStart(date); kolab.setDuration(Kolab::Duration(0, 0, 1, 0)); Kolab::RecurrenceRule rrule; rrule.setInterval(3); rrule.setFrequency(Kolab::RecurrenceRule::Daily); rrule.setEnd(date3); kolab.setRecurrenceRule(rrule); QTest::newRow("with duration and recurrence endDate") << kcal << kolab; } { Kolab::cDateTime start(2011,1,1); Kolab::cDateTime end(2011,1,3); KCalCore::Event kcal; kcal.setUid("uid"); kcal.setCreated(toDate(date)); kcal.setLastModified(toDate(date)); kcal.setDtStart(toDate(start)); kcal.setDtEnd(toDate(end)); kcal.recurrence()->setDaily(3); kcal.recurrence()->setEndDateTime(toDate(end)); Kolab::Event kolab; kolab.setUid("uid"); kolab.setCreated(date); kolab.setLastModified(date); kolab.setStart(start); kolab.setEnd(end); Kolab::RecurrenceRule rrule; rrule.setInterval(3); rrule.setFrequency(Kolab::RecurrenceRule::Daily); rrule.setEnd(end); kolab.setRecurrenceRule(rrule); QTest::newRow("date only dates") << kcal << kolab; } { KCalCore::Event kcal; kcal.setUid("uid"); kcal.setCreated(toDate(date)); kcal.setLastModified(toDate(date)); kcal.setDtStart(toDate(date)); kcal.setSummary("äöü%@$£é¤¼²°€Š�"); Kolab::Event kolab; kolab.setUid("uid"); kolab.setCreated(date); kolab.setLastModified(date); kolab.setStart(date); kolab.setSummary(std::string(QString("äöü%@$£é¤¼²°€Š�").toUtf8().constData())); QTest::newRow("latin1+Unicode") << kcal << kolab; } { KCalCore::Event kcal; kcal.setUid("uid"); kcal.setCreated(toDate(date)); kcal.setLastModified(toDate(date)); kcal.setRecurrenceId(toDate(date)); kcal.setThisAndFuture(true); Kolab::Event kolab; kolab.setUid("uid"); kolab.setCreated(date); kolab.setLastModified(date); kolab.setRecurrenceID(date, true); QTest::newRow("thisandfuture") << kcal << kolab; } } void KCalConversionTest::testConversion() { QFETCH(KCalCore::Event, kcal); QFETCH(Kolab::Event, kolab); KCalCore::Event::Ptr e = toKCalCore(kolab); const Kolab::Event &b = fromKCalCore(kcal); QCOMPARE(e->uid(), kcal.uid()); QCOMPARE(e->created(), kcal.created()); QCOMPARE(e->lastModified(), kcal.lastModified()); QCOMPARE(e->revision(), kcal.revision()); QCOMPARE(e->secrecy(), kcal.secrecy()); QCOMPARE(e->categories(), kcal.categories()); QCOMPARE(e->dtStart(), kcal.dtStart()); QCOMPARE(e->dtEnd(), kcal.dtEnd()); QCOMPARE(e->duration(), kcal.duration()); QCOMPARE(e->transparency(), kcal.transparency()); // QCOMPARE(*e->recurrence(), *kcal.recurrence()); QCOMPARE(e->recurrenceId(), kcal.recurrenceId()); QCOMPARE(e->thisAndFuture(), kcal.thisAndFuture()); QCOMPARE(e->recurrenceType(), kcal.recurrenceType()); QCOMPARE(e->summary(), kcal.summary()); QCOMPARE(e->description(), kcal.description()); QCOMPARE(e->priority(), kcal.priority()); QCOMPARE(e->status(), kcal.status()); QCOMPARE(e->location(), kcal.location()); +#ifndef LEGACY_KCALCORE QCOMPARE(e->organizer().name(), kcal.organizer().name()); QCOMPARE(e->organizer().email(), kcal.organizer().email()); +#endif QCOMPARE(e->nonKDECustomProperty("X-KOLAB-URL"), kcal.nonKDECustomProperty("X-KOLAB-URL")); //otherwise we'd break the customProperties comparison e->removeNonKDECustomProperty("X-KOLAB-URL"); kcal.removeNonKDECustomProperty("X-KOLAB-URL"); // compareAttendeesVectors(e->attendees(), kcal.attendees()); compareVectors(e->attachments(), kcal.attachments()); // QCOMPARE(e->alarms(), kcal.alarms()); //TODO QCOMPARE(e->customProperties(), kcal.customProperties()); // QBENCHMARK { // toKCalCore(kolab); // } QCOMPARE(b.uid(), kolab.uid()); QCOMPARE(b.created(), kolab.created()); QCOMPARE(b.lastModified(), kolab.lastModified()); QCOMPARE(b.sequence(), kolab.sequence()); QCOMPARE(b.classification(), kolab.classification()); QCOMPARE(b.categories(), kolab.categories()); // QCOMPARE(b.start(), kolab.start()); // QCOMPARE(b.end(), kolab.end()); QCOMPARE(b.duration(), kolab.duration()); QCOMPARE(b.transparency(), kolab.transparency()); // QCOMPARE(b.recurrenceRule(), kolab.recurrenceRule()); QCOMPARE(b.recurrenceID(), kolab.recurrenceID()); QCOMPARE(b.thisAndFuture(), kolab.thisAndFuture()); // QCOMPARE(b.recurrenceDates(), kolab.recurrenceDates()); // QCOMPARE(b.exceptionDates(), kolab.exceptionDates()); QCOMPARE(b.summary(), kolab.summary()); QCOMPARE(b.description(), kolab.description()); QCOMPARE(b.status(), kolab.status()); QCOMPARE(b.location(), kolab.location()); QCOMPARE(b.organizer(), kolab.organizer()); QCOMPARE(b.url(), kolab.url()); QCOMPARE(b.attendees(), kolab.attendees()); QCOMPARE(b.attachments(), kolab.attachments()); QCOMPARE(b.customProperties(), kolab.customProperties()); } void KCalConversionTest::testTodoConversion_data() { QTest::addColumn( "kcal" ); QTest::addColumn( "kolab" ); Kolab::cDateTime date(2011,2,2,12,11,10,true); Kolab::cDateTime date2(2011,2,2,12,12,10,true); { KCalCore::Todo kcal; kcal.setUid("uid"); kcal.setDtStart(toDate(date)); kcal.setDtDue(toDate(date2)); kcal.setRelatedTo("uid2", KCalCore::Incidence::RelTypeParent); Kolab::Todo kolab; kolab.setUid("uid"); kolab.setStart(date); kolab.setDue(date2); std::vector relateds; relateds.push_back("uid2"); kolab.setRelatedTo(relateds); QTest::newRow( "todo" ) << kcal << kolab; } } void KCalConversionTest::testTodoConversion() { QFETCH(KCalCore::Todo, kcal); QFETCH(Kolab::Todo, kolab); const KCalCore::Todo::Ptr e = toKCalCore(kolab); QCOMPARE(e->uid(), kcal.uid()); QCOMPARE(e->dtStart(), kcal.dtStart()); QCOMPARE(e->dtDue(), kcal.dtDue()); QCOMPARE(e->relatedTo(KCalCore::Incidence::RelTypeParent), kcal.relatedTo(KCalCore::Incidence::RelTypeParent)); const Kolab::Todo &b = fromKCalCore(kcal); QCOMPARE(b.uid(), kolab.uid()); QCOMPARE(b.start(), kolab.start()); QCOMPARE(b.due(), kolab.due()); QCOMPARE(b.relatedTo(), kolab.relatedTo()); } void KCalConversionTest::testJournalConversion_data() { QTest::addColumn( "kcal" ); QTest::addColumn( "kolab" ); Kolab::cDateTime date(2011,2,2,12,11,10,true); Kolab::cDateTime date2(2011,2,2,12,12,10,true); { KCalCore::Journal kcal; kcal.setUid("uid"); kcal.setDtStart(toDate(date)); kcal.setSummary("summary"); Kolab::Journal kolab; kolab.setUid("uid"); kolab.setStart(date); kolab.setSummary("summary"); QTest::newRow( "journal" ) << kcal << kolab; } } void KCalConversionTest::testJournalConversion() { QFETCH(KCalCore::Journal, kcal); QFETCH(Kolab::Journal, kolab); const KCalCore::Journal::Ptr e = toKCalCore(kolab); QCOMPARE(e->uid(), kcal.uid()); QCOMPARE(e->dtStart(), kcal.dtStart()); QCOMPARE(e->summary(), kcal.summary()); const Kolab::Journal &b = fromKCalCore(kcal); QCOMPARE(b.uid(), kolab.uid()); QCOMPARE(b.start(), kolab.start()); QCOMPARE(b.summary(), kolab.summary()); } QTEST_MAIN( KCalConversionTest ) #include "kcalconversiontest.moc"