aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Vrátil <[email protected]>2018-03-07 21:32:03 +0100
committerDaniel Vrátil <[email protected]>2018-03-07 21:42:51 +0100
commitfd2099c68d9d5cbc8e959582bc94552d0d30ee01 (patch)
tree18c803b73f358c342b288710cf61593ed96a5371
parentba21a30ae8d08223352bb0afadd5d1b262adeec6 (diff)
Import Akonadi Serializer plugins for incidences from kdepim-runtime
See commit cde643e6d840d591b6ae1b7f1a49488c495c4774 in kdepim-runtime for details.
-rw-r--r--CMakeLists.txt2
-rw-r--r--autotests/CMakeLists.txt7
-rw-r--r--autotests/kcalcoreserializertest.cpp135
-rw-r--r--serializers/CMakeLists.txt18
-rw-r--r--serializers/Messages.sh3
-rw-r--r--serializers/akonadi_serializer_kcalcore.cpp362
-rw-r--r--serializers/akonadi_serializer_kcalcore.desktop100
-rw-r--r--serializers/akonadi_serializer_kcalcore.h58
8 files changed, 684 insertions, 1 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 788e48e..aad48e0 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -66,7 +66,7 @@ add_definitions(-DQT_NO_URL_CAST_FROM_STRING)
#add_definitions(-DQT_DISABLE_DEPRECATED_BEFORE=0x060000)
add_subdirectory(src)
-
+add_subdirectory(serializers)
if (BUILD_TESTING)
add_subdirectory(autotests)
endif ()
diff --git a/autotests/CMakeLists.txt b/autotests/CMakeLists.txt
index db6c3fa..6919b76 100644
--- a/autotests/CMakeLists.txt
+++ b/autotests/CMakeLists.txt
@@ -1,4 +1,5 @@
include(ECMMarkAsTest)
+include(ECMAddTests)
set(QT_REQUIRED_VERSION "5.8.0")
find_package(Qt5Test ${QT_REQUIRED_VERSION} CONFIG REQUIRED)
@@ -26,3 +27,9 @@ add_akonadi_isolated_test_advanced( itiphandlertest.cpp "${common_sources}" "${c
add_akonadi_isolated_test_advanced( mailclienttest.cpp "" "KF5::AkonadiCalendar;KF5::Mime;KF5::MailTransportAkonadi;KF5::IdentityManagement")
endif()
+
+
+ecm_add_test(kcalcoreserializertest.cpp ../serializers/akonadi_serializer_kcalcore.cpp
+ LINK_LIBRARIES KF5::CalendarUtils KF5::CalendarCore KF5::AkonadiCore KF5::I18n Qt5::Test
+ TEST_NAME kcalcoreserializertest
+)
diff --git a/autotests/kcalcoreserializertest.cpp b/autotests/kcalcoreserializertest.cpp
new file mode 100644
index 0000000..0dac383
--- /dev/null
+++ b/autotests/kcalcoreserializertest.cpp
@@ -0,0 +1,135 @@
+/*
+ Copyright (c) 2009 Volker Krause <[email protected]>
+
+ 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 <AkonadiCore/Item>
+#include <KCalCore/Event>
+#include <qtest.h>
+#include <QObject>
+
+using namespace Akonadi;
+using namespace KCalCore;
+
+class KCalCoreSerializerTest : public QObject
+{
+ Q_OBJECT
+private Q_SLOTS:
+ void testEventSerialize_data()
+ {
+ QTest::addColumn<QString>("mimeType");
+ QTest::newRow("specific") << "application/x-vnd.akonadi.calendar.event";
+ QTest::newRow("generic") << "text/calendar";
+ }
+
+ void testCharsets_data()
+ {
+ testEventSerialize_data();
+ }
+
+ void testEventSerialize()
+ {
+ QFETCH(QString, mimeType);
+
+ QByteArray serialized
+ = "BEGIN:VCALENDAR\n"
+ "PRODID:-//K Desktop Environment//NONSGML libkcal 3.5//EN\n"
+ "VERSION:2.0\n"
+ "BEGIN:VEVENT\n"
+ "DTSTAMP:20070109T100625Z\n"
+ "ORGANIZER;CN=\"Volker Krause\":MAILTO:[email protected]\n"
+ "CREATED:20070109T100553Z\n"
+ "UID:libkcal-1135684253.945\n"
+ "SEQUENCE:1\n"
+ "LAST-MODIFIED:20070109T100625Z\n"
+ "SUMMARY:Test event\n"
+ "LOCATION:here\n"
+ "CLASS:PUBLIC\n"
+ "PRIORITY:5\n"
+ "CATEGORIES:KDE\n"
+ "DTSTART:20070109T183000Z\n"
+ "DTEND:20070109T225900Z\n"
+ "TRANSP:OPAQUE\n"
+ "BEGIN:VALARM\n"
+ "DESCRIPTION:\n"
+ "ACTION:DISPLAY\n"
+ "TRIGGER;VALUE=DURATION:-PT45M\n"
+ "END:VALARM\n"
+ "END:VEVENT\n"
+ "END:VCALENDAR\n";
+
+ // deserializing
+ Item item;
+ item.setMimeType(mimeType);
+ item.setPayloadFromData(serialized);
+
+ QVERIFY(item.hasPayload<Event::Ptr>());
+ const Event::Ptr event = item.payload<Event::Ptr>();
+ QVERIFY(event != nullptr);
+
+ QCOMPARE(event->summary(), QStringLiteral("Test event"));
+ QCOMPARE(event->location(), QStringLiteral("here"));
+
+ // serializing
+ const QByteArray data = item.payloadData();
+ QVERIFY(!data.isEmpty());
+ }
+
+ void testCharsets()
+ {
+ QFETCH(QString, mimeType);
+
+ // 0 defaults to latin1.
+ //QT5 QVERIFY( QTextCodec::codecForCStrings() == 0 );
+
+ const QDate currentDate = QDate::currentDate();
+
+ Event::Ptr event = Event::Ptr(new Event());
+ event->setUid(QStringLiteral("12345"));
+ event->setDtStart(QDateTime(currentDate, {}));
+ event->setDtEnd(QDateTime(currentDate.addDays(1), {}));
+ event->setAllDay(true);
+
+ // ü
+ const char latin1_umlaut[] = { static_cast<char>(0xFC), '\0' };
+ event->setSummary(QLatin1String(latin1_umlaut));
+
+ Item item;
+ item.setMimeType(mimeType);
+ item.setPayload(event);
+
+ // Serializer the item, the serialization should be in UTF-8:
+ const char utf_umlaut[] = { static_cast<char>(0xC3), static_cast<char>(0XBC), '\0' };
+ const QByteArray bytes = item.payloadData();
+ QVERIFY(bytes.contains(utf_umlaut));
+ QVERIFY(!bytes.contains(latin1_umlaut));
+
+ // Deserialize the data:
+ Item item2;
+ item2.setMimeType(mimeType);
+ item2.setPayloadFromData(bytes);
+
+ Event::Ptr event2 = item2.payload<Event::Ptr>();
+ QVERIFY(event2 != nullptr);
+ QVERIFY(event2->summary().toUtf8() == QByteArray(utf_umlaut));
+ QVERIFY(event2->summary().toLatin1() == QByteArray(latin1_umlaut));
+ }
+};
+
+QTEST_MAIN(KCalCoreSerializerTest)
+
+#include "kcalcoreserializertest.moc"
diff --git a/serializers/CMakeLists.txt b/serializers/CMakeLists.txt
new file mode 100644
index 0000000..69e1edb
--- /dev/null
+++ b/serializers/CMakeLists.txt
@@ -0,0 +1,18 @@
+add_definitions(-DTRANSLATION_DOMAIN=\"libakonadi-calendar5-serializer\")
+
+set(akonadi_serializer_kcalcore_SRCS
+ akonadi_serializer_kcalcore.cpp
+)
+add_library(akonadi_serializer_kcalcore MODULE ${akonadi_serializer_kcalcore_SRCS})
+target_link_libraries(akonadi_serializer_kcalcore
+ KF5::CalendarUtils
+ KF5::CalendarCore
+ KF5::AkonadiCore
+ KF5::I18n
+)
+install(TARGETS akonadi_serializer_kcalcore
+ DESTINATION ${KDE_INSTALL_PLUGINDIR}
+)
+install(FILES akonadi_serializer_kcalcore.desktop
+ DESTINATION ${KDE_INSTALL_DATADIR}/akonadi/plugins/serializer
+)
diff --git a/serializers/Messages.sh b/serializers/Messages.sh
new file mode 100644
index 0000000..d1363e5
--- /dev/null
+++ b/serializers/Messages.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+$XGETTEXT *.cpp -o $podir/libakonadi-calendar5-serializer.pot
+
diff --git a/serializers/akonadi_serializer_kcalcore.cpp b/serializers/akonadi_serializer_kcalcore.cpp
new file mode 100644
index 0000000..4e9b5f2
--- /dev/null
+++ b/serializers/akonadi_serializer_kcalcore.cpp
@@ -0,0 +1,362 @@
+/*
+ Copyright (c) 2007 Volker Krause <[email protected]>
+
+ 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 <AkonadiCore/AbstractDifferencesReporter>
+#include <AkonadiCore/Item>
+#include <AkonadiCore/Collection>
+
+#include <KCalCore/Event>
+#include <KCalCore/Todo>
+
+#include <KCalUtils/Stringify>
+
+#include <KLocalizedString>
+
+#include <QDate>
+#include <QDebug>
+
+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<KCalCore::Incidence::IncidenceType>(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;
+ default:
+ break;
+ }
+ input >> base;
+ incidence = base.staticCast<KCalCore::Incidence>();
+ } else {
+ // Use the old format
+ incidence = mFormat.readIncidence(data.readAll());
+ }
+
+ if (!incidence) {
+ qWarning() << "Failed to parse incidence! Item id = " << item.id()
+ << "Storage collection id " << item.storageCollectionId()
+ << "parentCollectionId = " << item.parentCollection().id();
+ data.seek(0);
+ qWarning() << 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<Incidence::Ptr>()) {
+ return;
+ }
+ Incidence::Ptr i = item.payload<Incidence::Ptr>();
+
+ // 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::Ptr &attendee)
+{
+ return attendee->name() + QLatin1Char('<') + attendee->email() + QLatin1Char('>');
+}
+
+static QString toString(const Alarm::Ptr &)
+{
+ return QString();
+}
+
+static QString toString(const Attachment::Ptr &)
+{
+ 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<class C>
+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<Incidence::Ptr>());
+ Q_ASSERT(rightItem.hasPayload<Incidence::Ptr>());
+
+ const Incidence::Ptr leftIncidencePtr = leftItem.payload<Incidence::Ptr>();
+ const Incidence::Ptr rightIncidencePtr = rightItem.payload<Incidence::Ptr>();
+
+ 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<Event>();
+ const Event::Ptr rightEvent = rightIncidencePtr.dynamicCast<Event>();
+ if (leftEvent && rightEvent) {
+ compareEvent(reporter, leftEvent, rightEvent);
+ } else {
+ const Todo::Ptr leftTodo = leftIncidencePtr.dynamicCast<Todo>();
+ const Todo::Ptr rightTodo = rightIncidencePtr.dynamicCast<Todo>();
+ if (leftTodo && rightTodo) {
+ compareTodo(reporter, leftTodo, rightTodo);
+ }
+ }
+}
+
+//// GidExtractorInterface
+
+QString SerializerPluginKCalCore::extractGid(const Item &item) const
+{
+ if (!item.hasPayload<Incidence::Ptr>()) {
+ return QString();
+ }
+ return item.payload<Incidence::Ptr>()->instanceIdentifier();
+}
diff --git a/serializers/akonadi_serializer_kcalcore.desktop b/serializers/akonadi_serializer_kcalcore.desktop
new file mode 100644
index 0000000..023433a
--- /dev/null
+++ b/serializers/akonadi_serializer_kcalcore.desktop
@@ -0,0 +1,100 @@
+[Misc]
+Name=Incidence Serializer
+Name[ar]=مُسلسِل الحدوثات
+Name[bs]=Seralizator događaja
+Name[ca]=Serialitzador d'incidències
+Name[[email protected]]=Serialitzador d'incidències
+Name[da]=Serieordning af hændelser
+Name[de]=Ereignis-Serialisierung
+Name[el]=Σειριακοποιητής περιστατικών
+Name[en_GB]=Incidence Serialiser
+Name[es]=Serializador de incidencias
+Name[et]=Sündmuste jadasti
+Name[fi]=Merkintäserialisoija
+Name[fr]=Sérialiseur d'évènements
+Name[ga]=Srathóir Imeachtaí
+Name[gl]=Serializador de incidencias
+Name[hu]=Eseménykezelő
+Name[ia]=Divulgator partial de incidentias
+Name[it]=Serializzatore occorrenze
+Name[ja]=イベント用シリアライザ
+Name[kk]=Істерді тізбектеуіші
+Name[km]=Incidence Serializer
+Name[ko]=사건 시리얼라이저
+Name[lt]=Įvykių serializatorius
+Name[lv]=Notikumu serializētājs
+Name[nb]=Forekomst-serialisering
+Name[nds]=Begeefnis-Reegmoduul
+Name[ne]=घटना मिलानकर्ता
+Name[nl]=Agenda-item-administratie
+Name[nn]=Hendingsserialisator
+Name[pl]=Szeregowanie zdarzeń
+Name[pt]=Serializador de Incidências
+Name[pt_BR]=Serializador de incidências
+Name[ro]=Serializator incidență
+Name[ru]=Сохранение событий
+Name[sk]=Serializátor výskytu
+Name[sl]=Razvrščevalnik pojavitev v zaporedje
+Name[sr]=Серијализатор случајева
+Name[[email protected]]=Серијализатор случајева
+Name[[email protected]]=Serijalizator slučajeva
+Name[[email protected]]=Serijalizator slučajeva
+Name[sv]=Förekomstserialisering
+Name[tr]=Olay Sıralandırıcısı
+Name[uk]=Серіалізатор подій
+Name[x-test]=xxIncidence Serializerxx
+Name[zh_CN]=事件序列转换器
+Name[zh_TW]=頻率序列器
+Comment=An Akonadi serializer plugin for events, tasks and journal entries
+Comment[ar]=ملحقة سَلسَلة «أكونادي» للأحداث والمهامّ ومدخلات اليوميّة
+Comment[bs]=Akonadi dodatak serializatora za događaje, zadatke i žurnal upise
+Comment[ca]=Un connector de serialització de l'Akonadi pels objectes d'incidències
+Comment[[email protected]]=Un connector de serialització de l'Akonadi pels objectes d'incidències
+Comment[da]=Et Akonadi-plugin til serieordning af hændelser, opgaver og journalindgange
+Comment[de]=Akonadi-Modul zur Serialisierung von Ereignissen
+Comment[el]=Ένα πρόσθετο σειριακοποιητή Akonadi για γεγονότα, εργασίες και καταχωρήσεις χρονικού
+Comment[en_GB]=An Akonadi serialiser plugin for events, tasks and journal entries
+Comment[es]=Un complemento serializador de Akonadi para eventos, tareas y entradas del diario
+Comment[et]=Akonadi sündmuste, ülesannete ja päevikusissekannate jadastamisplugin
+Comment[fi]=Akonadi-serialisoijaliitännäinen tapahtumia, tehtäviä ja päiväkirjamerkintöjä varten.
+Comment[fr]=Un module externe Akonadi pour la sérialisation des évènements
+Comment[ga]=Breiseán srathóra Akonadi le haghaidh imeachtaí, tascanna, agus iontrálacha dialainne
+Comment[gl]=Un complemento de serialización de Akonadi para eventos, tarefas e entradas do diario
+Comment[hu]=Akonadi-modul események, feladatok és naplóbejegyzések kezeléséhez
+Comment[ia]=Un plug-in pro divulgator partial de Akonadi pro eventos, cargas e jornales
+Comment[it]=Un'estensione di Akonadi per la serializzazione di eventi, attività e diari
+Comment[ja]=イベント、タスク、日記のエントリのための Akonadi シリアライザプラグイン
+Comment[kk]=Akonadi оқиға, тапсырма, күнделік жазуларының тізбектеуіш плагині
+Comment[km]=កម្មវិធី​ជំនួយ​កម្មវិធី​បោះពុម្ព Akonadi សម្រាប់​ធាតុ​​ព្រឹត្តិការណ៍ ភារកិច្ច និង​ទិនានុប្បវត្តិ
+Comment[ko]=행사, 작업, 저널 항목을 위한 Akonadi 시리얼라이저 플러그인
+Comment[lt]=Akonadi serializatoriaus papildinys įvykiams, užduotims ir dienoraščio įrašams
+Comment[lv]=Akonadi notikumu, uzdevumu un dienasgrāmatas ierakstu serializēšanas spraudnis
+Comment[nb]=Et Akonadi programtillegg for serialisering av hendelser, gjøremål og dagboksnotater
+Comment[nds]=Akonadi-Inreegmoduul för Begeefnissen, Opgaven un Daagbookindrääg
+Comment[ne]=घटना, कार्य र जर्नल भौचरका लागि एउटा एकोनाडी मिलानकर्ता प्लगइन
+Comment[nl]=Een administratieplug-in voor Akonadi voor evenementen, taken en journalen
+Comment[nn]=Eit Akonadi-serialisatortillegg for hendingar, oppgåver og dagboktekstar
+Comment[pa]=ਈਵੈਂਟ, ਟਾਸਕ ਅਤੇ ਜਰਨਲ ਐਂਟਰੀਆਂ ਲਈ ਅਕੌਂਡੀ ਸੀਰੀਲਾਈਜ਼ਰ ਪਲੱਗਇਨ
+Comment[pl]=Wtyczka Akonadi do szeregowania zdarzeń, zadań i wpisów w dzienniku
+Comment[pt]=Um 'plugin' de serialização do Akonadi para os eventos, tarefas e itens do diário
+Comment[pt_BR]=Um plugin de serialização do Akonadi para os eventos, tarefas e entradas do diário
+Comment[ro]=Modul de serializare Akonadi pentru evenimente, sarcini și întregistrări de agendă
+Comment[ru]=Модуль сохранения событий, задач и записей дневника для Akonadi
+Comment[sk]=Plugin serializátora Akonadi pre udalosti, úlohy a položky denníka
+Comment[sl]=Akonadijev vstavek za razvrščanje predmetov pojavitev v zaporedje
+Comment[sr]=Аконадијев прикључак серијализатора за догађаје, послове и уносе дневника
+Comment[[email protected]]=Аконадијев прикључак серијализатора за догађаје, послове и уносе дневника
+Comment[[email protected]]=Akonadijev priključak serijalizatora za događaje, poslove i unose dnevnika
+Comment[[email protected]]=Akonadijev priključak serijalizatora za događaje, poslove i unose dnevnika
+Comment[sv]=Ett insticksprogram till Akonadi för serialisering av händelser, uppgifter och journalanteckningar
+Comment[tr]=Olay, görev ve günlük nesneleri için bir Akonadi sıralandırıcısı
+Comment[uk]="Додаток серіалізації Akonadi для подій, завдань і записів журналів"
+Comment[x-test]=xxAn Akonadi serializer plugin for events, tasks and journal entriesxx
+Comment[zh_CN]=对事项、任务和日记项进行序列转换的 Akonadi 插件
+Comment[zh_TW]=事件、工作與日誌項目物件的 Akonadi 序列器外掛程式
+
+[Plugin]
+Type=text/calendar,application/x-vnd.akonadi.note,application/x-vnd.kde.notes
+X-Akonadi-Class=default;KCalCore::Incidence*;
+X-KDE-Library=akonadi_serializer_kcalcore
+X-KDE-ClassName=Akonadi::SerializerPluginKCalCore
diff --git a/serializers/akonadi_serializer_kcalcore.h b/serializers/akonadi_serializer_kcalcore.h
new file mode 100644
index 0000000..96bd055
--- /dev/null
+++ b/serializers/akonadi_serializer_kcalcore.h
@@ -0,0 +1,58 @@
+/*
+ Copyright (c) 2007 Volker Krause <[email protected]>
+
+ 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.
+*/
+
+#ifndef AKONADI_SERIALIZER_KCALCORE_H
+#define AKONADI_SERIALIZER_KCALCORE_H
+
+#include <QObject>
+
+#include <AkonadiCore/differencesalgorithminterface.h>
+#include <AkonadiCore/itemserializerplugin.h>
+#include <AkonadiCore/gidextractorinterface.h>
+
+#include <KCalCore/ICalFormat>
+
+namespace Akonadi {
+
+class SerializerPluginKCalCore : public QObject
+ , public ItemSerializerPlugin
+ , public DifferencesAlgorithmInterface
+ , public GidExtractorInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(Akonadi::ItemSerializerPlugin)
+ Q_INTERFACES(Akonadi::DifferencesAlgorithmInterface)
+ Q_INTERFACES(Akonadi::GidExtractorInterface)
+ Q_PLUGIN_METADATA(IID "org.kde.akonadi.SerializerPluginKCalCore")
+public:
+ SerializerPluginKCalCore();
+ bool deserialize(Item &item, const QByteArray &label, QIODevice &data, int version) override;
+ void serialize(const Item &item, const QByteArray &label, QIODevice &data, int &version) override;
+
+ void compare(Akonadi::AbstractDifferencesReporter *reporter, const Akonadi::Item &leftItem, const Akonadi::Item &rightItem) override;
+
+ QString extractGid(const Item &item) const override;
+
+private:
+ KCalCore::ICalFormat mFormat;
+};
+
+}
+
+#endif