diff options
-rw-r--r-- | common/CMakeLists.txt | 2 | ||||
-rw-r--r-- | common/domain/applicationdomaintype.cpp | 13 | ||||
-rw-r--r-- | common/domain/applicationdomaintype.h | 17 | ||||
-rw-r--r-- | common/domain/applicationdomaintype_p.h | 2 | ||||
-rw-r--r-- | common/domain/propertyregistry.cpp | 6 | ||||
-rw-r--r-- | common/domain/todo.fbs | 18 | ||||
-rw-r--r-- | common/domain/typeimplementations.cpp | 35 | ||||
-rw-r--r-- | common/domain/typeimplementations.h | 12 | ||||
-rw-r--r-- | common/propertymapper.cpp | 36 | ||||
-rw-r--r-- | common/propertymapper.h | 8 | ||||
-rw-r--r-- | common/synchronizer.cpp | 7 | ||||
-rw-r--r-- | common/synchronizer.h | 1 | ||||
-rw-r--r-- | common/todopreprocessor.cpp | 67 | ||||
-rw-r--r-- | common/todopreprocessor.h | 35 | ||||
-rw-r--r-- | examples/caldavresource/caldavresource.cpp | 105 | ||||
-rw-r--r-- | examples/caldavresource/tests/caldavtest.cpp | 111 |
16 files changed, 432 insertions, 43 deletions
diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 40c955e..c8e178a 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt | |||
@@ -71,6 +71,7 @@ set(command_SRCS | |||
71 | contactpreprocessor.cpp | 71 | contactpreprocessor.cpp |
72 | mailpreprocessor.cpp | 72 | mailpreprocessor.cpp |
73 | eventpreprocessor.cpp | 73 | eventpreprocessor.cpp |
74 | todopreprocessor.cpp | ||
74 | specialpurposepreprocessor.cpp | 75 | specialpurposepreprocessor.cpp |
75 | datastorequery.cpp | 76 | datastorequery.cpp |
76 | storage/entitystore.cpp | 77 | storage/entitystore.cpp |
@@ -105,6 +106,7 @@ generate_flatbuffers( | |||
105 | domain/contact | 106 | domain/contact |
106 | domain/addressbook | 107 | domain/addressbook |
107 | domain/event | 108 | domain/event |
109 | domain/todo | ||
108 | domain/calendar | 110 | domain/calendar |
109 | domain/mail | 111 | domain/mail |
110 | domain/folder | 112 | domain/folder |
diff --git a/common/domain/applicationdomaintype.cpp b/common/domain/applicationdomaintype.cpp index 78d46ee..b1469e1 100644 --- a/common/domain/applicationdomaintype.cpp +++ b/common/domain/applicationdomaintype.cpp | |||
@@ -132,6 +132,19 @@ SINK_REGISTER_PROPERTY(Event, EndTime); | |||
132 | SINK_REGISTER_PROPERTY(Event, Ical); | 132 | SINK_REGISTER_PROPERTY(Event, Ical); |
133 | SINK_REGISTER_PROPERTY(Event, Calendar); | 133 | SINK_REGISTER_PROPERTY(Event, Calendar); |
134 | 134 | ||
135 | SINK_REGISTER_ENTITY(Todo); | ||
136 | SINK_REGISTER_PROPERTY(Todo, Uid); | ||
137 | SINK_REGISTER_PROPERTY(Todo, Summary); | ||
138 | SINK_REGISTER_PROPERTY(Todo, Description); | ||
139 | SINK_REGISTER_PROPERTY(Todo, CompletedDate); | ||
140 | SINK_REGISTER_PROPERTY(Todo, DueDate); | ||
141 | SINK_REGISTER_PROPERTY(Todo, StartDate); | ||
142 | SINK_REGISTER_PROPERTY(Todo, Status); | ||
143 | SINK_REGISTER_PROPERTY(Todo, Priority); | ||
144 | SINK_REGISTER_PROPERTY(Todo, Categories); | ||
145 | SINK_REGISTER_PROPERTY(Todo, Ical); | ||
146 | SINK_REGISTER_PROPERTY(Todo, Calendar); | ||
147 | |||
135 | SINK_REGISTER_ENTITY(Calendar); | 148 | SINK_REGISTER_ENTITY(Calendar); |
136 | SINK_REGISTER_PROPERTY(Calendar, Name); | 149 | SINK_REGISTER_PROPERTY(Calendar, Name); |
137 | 150 | ||
diff --git a/common/domain/applicationdomaintype.h b/common/domain/applicationdomaintype.h index 39e66ab..93de8f5 100644 --- a/common/domain/applicationdomaintype.h +++ b/common/domain/applicationdomaintype.h | |||
@@ -407,6 +407,17 @@ struct SINK_EXPORT Event : public Entity { | |||
407 | 407 | ||
408 | struct SINK_EXPORT Todo : public Entity { | 408 | struct SINK_EXPORT Todo : public Entity { |
409 | SINK_ENTITY(Todo, todo); | 409 | SINK_ENTITY(Todo, todo); |
410 | SINK_EXTRACTED_PROPERTY(QString, Uid, uid); | ||
411 | SINK_EXTRACTED_PROPERTY(QString, Summary, summary); | ||
412 | SINK_EXTRACTED_PROPERTY(QString, Description, description); | ||
413 | SINK_EXTRACTED_PROPERTY(QDateTime, CompletedDate, completedDate); | ||
414 | SINK_EXTRACTED_PROPERTY(QDateTime, DueDate, dueDate); | ||
415 | SINK_EXTRACTED_PROPERTY(QDateTime, StartDate, startDate); | ||
416 | SINK_EXTRACTED_PROPERTY(QString, Status, status); | ||
417 | SINK_EXTRACTED_PROPERTY(int, Priority, priority); | ||
418 | SINK_EXTRACTED_PROPERTY(QStringList, Categories, categories); | ||
419 | SINK_PROPERTY(QByteArray, Ical, ical); | ||
420 | SINK_REFERENCE_PROPERTY(Calendar, Calendar, calendar); | ||
410 | }; | 421 | }; |
411 | 422 | ||
412 | struct SINK_EXPORT Folder : public Entity { | 423 | struct SINK_EXPORT Folder : public Entity { |
@@ -506,6 +517,11 @@ namespace Event { | |||
506 | static constexpr const char *calendar = "calendar"; | 517 | static constexpr const char *calendar = "calendar"; |
507 | static constexpr const char *storage = "event.storage"; | 518 | static constexpr const char *storage = "event.storage"; |
508 | }; | 519 | }; |
520 | namespace Todo { | ||
521 | static constexpr const char *todo = "todo"; | ||
522 | static constexpr const char *calendar = "calendar"; | ||
523 | static constexpr const char *storage = "todo.storage"; | ||
524 | }; | ||
509 | }; | 525 | }; |
510 | 526 | ||
511 | namespace SpecialPurpose { | 527 | namespace SpecialPurpose { |
@@ -558,6 +574,7 @@ class SINK_EXPORT TypeImplementation; | |||
558 | REGISTER_TYPE(Sink::ApplicationDomain::Contact) \ | 574 | REGISTER_TYPE(Sink::ApplicationDomain::Contact) \ |
559 | REGISTER_TYPE(Sink::ApplicationDomain::Addressbook) \ | 575 | REGISTER_TYPE(Sink::ApplicationDomain::Addressbook) \ |
560 | REGISTER_TYPE(Sink::ApplicationDomain::Event) \ | 576 | REGISTER_TYPE(Sink::ApplicationDomain::Event) \ |
577 | REGISTER_TYPE(Sink::ApplicationDomain::Todo) \ | ||
561 | REGISTER_TYPE(Sink::ApplicationDomain::Calendar) \ | 578 | REGISTER_TYPE(Sink::ApplicationDomain::Calendar) \ |
562 | REGISTER_TYPE(Sink::ApplicationDomain::Mail) \ | 579 | REGISTER_TYPE(Sink::ApplicationDomain::Mail) \ |
563 | REGISTER_TYPE(Sink::ApplicationDomain::Folder) \ | 580 | REGISTER_TYPE(Sink::ApplicationDomain::Folder) \ |
diff --git a/common/domain/applicationdomaintype_p.h b/common/domain/applicationdomaintype_p.h index 734ac3e..248f6f0 100644 --- a/common/domain/applicationdomaintype_p.h +++ b/common/domain/applicationdomaintype_p.h | |||
@@ -38,6 +38,8 @@ struct TypeHelper { | |||
38 | return Func<Sink::ApplicationDomain::Mail>{}(std::forward<Args...>(args...)); | 38 | return Func<Sink::ApplicationDomain::Mail>{}(std::forward<Args...>(args...)); |
39 | } else if (type == Sink::ApplicationDomain::getTypeName<Sink::ApplicationDomain::Event>()) { | 39 | } else if (type == Sink::ApplicationDomain::getTypeName<Sink::ApplicationDomain::Event>()) { |
40 | return Func<Sink::ApplicationDomain::Event>{}(std::forward<Args...>(args...)); | 40 | return Func<Sink::ApplicationDomain::Event>{}(std::forward<Args...>(args...)); |
41 | } else if (type == Sink::ApplicationDomain::getTypeName<Sink::ApplicationDomain::Todo>()) { | ||
42 | return Func<Sink::ApplicationDomain::Todo>{}(std::forward<Args...>(args...)); | ||
41 | } else if (type == Sink::ApplicationDomain::getTypeName<Sink::ApplicationDomain::Calendar>()) { | 43 | } else if (type == Sink::ApplicationDomain::getTypeName<Sink::ApplicationDomain::Calendar>()) { |
42 | return Func<Sink::ApplicationDomain::Calendar>{}(std::forward<Args...>(args...)); | 44 | return Func<Sink::ApplicationDomain::Calendar>{}(std::forward<Args...>(args...)); |
43 | } else if (type == Sink::ApplicationDomain::getTypeName<Sink::ApplicationDomain::Contact>()) { | 45 | } else if (type == Sink::ApplicationDomain::getTypeName<Sink::ApplicationDomain::Contact>()) { |
diff --git a/common/domain/propertyregistry.cpp b/common/domain/propertyregistry.cpp index d929d68..00bbb1d 100644 --- a/common/domain/propertyregistry.cpp +++ b/common/domain/propertyregistry.cpp | |||
@@ -75,6 +75,12 @@ QVariant parseString<QList<QByteArray>>(const QString &s) | |||
75 | } | 75 | } |
76 | 76 | ||
77 | template <> | 77 | template <> |
78 | QVariant parseString<QStringList>(const QString &s) | ||
79 | { | ||
80 | return s.split(','); | ||
81 | } | ||
82 | |||
83 | template <> | ||
78 | QVariant parseString<QDateTime>(const QString &s) | 84 | QVariant parseString<QDateTime>(const QString &s) |
79 | { | 85 | { |
80 | return QVariant::fromValue(QDateTime::fromString(s, Qt::ISODate)); | 86 | return QVariant::fromValue(QDateTime::fromString(s, Qt::ISODate)); |
diff --git a/common/domain/todo.fbs b/common/domain/todo.fbs new file mode 100644 index 0000000..b448cae --- /dev/null +++ b/common/domain/todo.fbs | |||
@@ -0,0 +1,18 @@ | |||
1 | namespace Sink.ApplicationDomain.Buffer; | ||
2 | |||
3 | table Todo { | ||
4 | uid:string; | ||
5 | summary:string; | ||
6 | description:string; | ||
7 | completedDate:string; | ||
8 | dueDate:string; | ||
9 | startDate:string; | ||
10 | status:string; | ||
11 | priority:int; | ||
12 | categories:[string]; | ||
13 | ical:string; | ||
14 | calendar:string; | ||
15 | } | ||
16 | |||
17 | root_type Todo; | ||
18 | file_identifier "AKFB"; | ||
diff --git a/common/domain/typeimplementations.cpp b/common/domain/typeimplementations.cpp index 615c8e8..b584138 100644 --- a/common/domain/typeimplementations.cpp +++ b/common/domain/typeimplementations.cpp | |||
@@ -67,6 +67,10 @@ typedef IndexConfig<Event, | |||
67 | ValueIndex<Event::Uid> | 67 | ValueIndex<Event::Uid> |
68 | > EventIndexConfig; | 68 | > EventIndexConfig; |
69 | 69 | ||
70 | typedef IndexConfig<Todo, | ||
71 | ValueIndex<Todo::Uid> | ||
72 | > TodoIndexConfig; | ||
73 | |||
70 | typedef IndexConfig<Calendar, | 74 | typedef IndexConfig<Calendar, |
71 | ValueIndex<Calendar::Name> | 75 | ValueIndex<Calendar::Name> |
72 | > CalendarIndexConfig; | 76 | > CalendarIndexConfig; |
@@ -218,6 +222,37 @@ void TypeImplementation<Event>::configure(IndexPropertyMapper &) | |||
218 | } | 222 | } |
219 | 223 | ||
220 | 224 | ||
225 | void TypeImplementation<Todo>::configure(TypeIndex &index) | ||
226 | { | ||
227 | TodoIndexConfig::configure(index); | ||
228 | } | ||
229 | |||
230 | QMap<QByteArray, int> TypeImplementation<Todo>::typeDatabases() | ||
231 | { | ||
232 | return merge(QMap<QByteArray, int>{{QByteArray{Todo::name} + ".main", 0}}, TodoIndexConfig::databases()); | ||
233 | } | ||
234 | |||
235 | void TypeImplementation<Todo>::configure(PropertyMapper &propertyMapper) | ||
236 | { | ||
237 | SINK_REGISTER_SERIALIZER(propertyMapper, Todo, Uid, uid); | ||
238 | SINK_REGISTER_SERIALIZER(propertyMapper, Todo, Summary, summary); | ||
239 | SINK_REGISTER_SERIALIZER(propertyMapper, Todo, Description, description); | ||
240 | SINK_REGISTER_SERIALIZER(propertyMapper, Todo, CompletedDate, completedDate); | ||
241 | SINK_REGISTER_SERIALIZER(propertyMapper, Todo, DueDate, dueDate); | ||
242 | SINK_REGISTER_SERIALIZER(propertyMapper, Todo, StartDate, startDate); | ||
243 | SINK_REGISTER_SERIALIZER(propertyMapper, Todo, Status, status); | ||
244 | SINK_REGISTER_SERIALIZER(propertyMapper, Todo, Priority, priority); | ||
245 | SINK_REGISTER_SERIALIZER(propertyMapper, Todo, Categories, categories); | ||
246 | SINK_REGISTER_SERIALIZER(propertyMapper, Todo, Ical, ical); | ||
247 | SINK_REGISTER_SERIALIZER(propertyMapper, Todo, Calendar, calendar); | ||
248 | } | ||
249 | |||
250 | void TypeImplementation<Todo>::configure(IndexPropertyMapper &) | ||
251 | { | ||
252 | |||
253 | } | ||
254 | |||
255 | |||
221 | void TypeImplementation<Calendar>::configure(TypeIndex &index) | 256 | void TypeImplementation<Calendar>::configure(TypeIndex &index) |
222 | { | 257 | { |
223 | CalendarIndexConfig::configure(index); | 258 | CalendarIndexConfig::configure(index); |
diff --git a/common/domain/typeimplementations.h b/common/domain/typeimplementations.h index 672e83a..5c6ba14 100644 --- a/common/domain/typeimplementations.h +++ b/common/domain/typeimplementations.h | |||
@@ -24,6 +24,7 @@ | |||
24 | #include "mail_generated.h" | 24 | #include "mail_generated.h" |
25 | #include "folder_generated.h" | 25 | #include "folder_generated.h" |
26 | #include "event_generated.h" | 26 | #include "event_generated.h" |
27 | #include "todo_generated.h" | ||
27 | #include "calendar_generated.h" | 28 | #include "calendar_generated.h" |
28 | #include "contact_generated.h" | 29 | #include "contact_generated.h" |
29 | #include "addressbook_generated.h" | 30 | #include "addressbook_generated.h" |
@@ -97,6 +98,17 @@ public: | |||
97 | }; | 98 | }; |
98 | 99 | ||
99 | template<> | 100 | template<> |
101 | class SINK_EXPORT TypeImplementation<Sink::ApplicationDomain::Todo> { | ||
102 | public: | ||
103 | typedef Sink::ApplicationDomain::Buffer::Todo Buffer; | ||
104 | typedef Sink::ApplicationDomain::Buffer::TodoBuilder BufferBuilder; | ||
105 | static void configure(TypeIndex &); | ||
106 | static void configure(PropertyMapper &); | ||
107 | static void configure(IndexPropertyMapper &indexPropertyMapper); | ||
108 | static QMap<QByteArray, int> typeDatabases(); | ||
109 | }; | ||
110 | |||
111 | template<> | ||
100 | class SINK_EXPORT TypeImplementation<Sink::ApplicationDomain::Calendar> { | 112 | class SINK_EXPORT TypeImplementation<Sink::ApplicationDomain::Calendar> { |
101 | public: | 113 | public: |
102 | typedef Sink::ApplicationDomain::Buffer::Calendar Buffer; | 114 | typedef Sink::ApplicationDomain::Buffer::Calendar Buffer; |
diff --git a/common/propertymapper.cpp b/common/propertymapper.cpp index 7c313cc..f9f9c9b 100644 --- a/common/propertymapper.cpp +++ b/common/propertymapper.cpp | |||
@@ -82,6 +82,21 @@ flatbuffers::uoffset_t variantToProperty<QByteArrayList>(const QVariant &propert | |||
82 | } | 82 | } |
83 | 83 | ||
84 | template <> | 84 | template <> |
85 | flatbuffers::uoffset_t variantToProperty<QStringList>(const QVariant &property, flatbuffers::FlatBufferBuilder &fbb) | ||
86 | { | ||
87 | if (property.isValid()) { | ||
88 | const auto list = property.value<QStringList>(); | ||
89 | std::vector<flatbuffers::Offset<flatbuffers::String>> vector; | ||
90 | for (const auto &value : list) { | ||
91 | auto offset = fbb.CreateString(value.toStdString()); | ||
92 | vector.push_back(offset); | ||
93 | } | ||
94 | return fbb.CreateVector(vector).o; | ||
95 | } | ||
96 | return 0; | ||
97 | } | ||
98 | |||
99 | template <> | ||
85 | flatbuffers::uoffset_t variantToProperty<Sink::ApplicationDomain::Mail::Contact>(const QVariant &property, flatbuffers::FlatBufferBuilder &fbb) | 100 | flatbuffers::uoffset_t variantToProperty<Sink::ApplicationDomain::Mail::Contact>(const QVariant &property, flatbuffers::FlatBufferBuilder &fbb) |
86 | { | 101 | { |
87 | if (property.isValid()) { | 102 | if (property.isValid()) { |
@@ -187,6 +202,21 @@ QVariant propertyToVariant<QByteArrayList>(const flatbuffers::Vector<flatbuffers | |||
187 | } | 202 | } |
188 | 203 | ||
189 | template <> | 204 | template <> |
205 | QVariant propertyToVariant<QStringList>(const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *property) | ||
206 | { | ||
207 | if (property) { | ||
208 | QStringList list; | ||
209 | for (auto it = property->begin(); it != property->end();) { | ||
210 | // We have to copy the memory, otherwise it would become eventually invalid | ||
211 | list << QString::fromStdString((*it)->str()); | ||
212 | it.operator++(); | ||
213 | } | ||
214 | return QVariant::fromValue(list); | ||
215 | } | ||
216 | return QVariant(); | ||
217 | } | ||
218 | |||
219 | template <> | ||
190 | QVariant propertyToVariant<Sink::ApplicationDomain::Mail::Contact>(const Sink::ApplicationDomain::Buffer::MailContact *property) | 220 | QVariant propertyToVariant<Sink::ApplicationDomain::Mail::Contact>(const Sink::ApplicationDomain::Buffer::MailContact *property) |
191 | { | 221 | { |
192 | if (property) { | 222 | if (property) { |
@@ -232,6 +262,12 @@ QVariant propertyToVariant<bool>(uint8_t property) | |||
232 | } | 262 | } |
233 | 263 | ||
234 | template <> | 264 | template <> |
265 | QVariant propertyToVariant<int>(uint8_t property) | ||
266 | { | ||
267 | return static_cast<int>(property); | ||
268 | } | ||
269 | |||
270 | template <> | ||
235 | QVariant propertyToVariant<QDateTime>(const flatbuffers::String *property) | 271 | QVariant propertyToVariant<QDateTime>(const flatbuffers::String *property) |
236 | { | 272 | { |
237 | if (property) { | 273 | if (property) { |
diff --git a/common/propertymapper.h b/common/propertymapper.h index fd24278..49224fa 100644 --- a/common/propertymapper.h +++ b/common/propertymapper.h | |||
@@ -131,6 +131,14 @@ private: | |||
131 | } | 131 | } |
132 | 132 | ||
133 | template <typename T, typename BufferBuilder> | 133 | template <typename T, typename BufferBuilder> |
134 | void addWriteMapping(void (BufferBuilder::*f)(int)) | ||
135 | { | ||
136 | addWriteMapping(T::name, [f](const QVariant &value, flatbuffers::FlatBufferBuilder &fbb) -> std::function<void(void *builder)> { | ||
137 | return [value, f](void *builder) { (static_cast<BufferBuilder*>(builder)->*f)(value.value<typename T::Type>()); }; | ||
138 | }); | ||
139 | } | ||
140 | |||
141 | template <typename T, typename BufferBuilder> | ||
134 | void addWriteMapping(void (BufferBuilder::*f)(bool)) | 142 | void addWriteMapping(void (BufferBuilder::*f)(bool)) |
135 | { | 143 | { |
136 | addWriteMapping(T::name, [f](const QVariant &value, flatbuffers::FlatBufferBuilder &fbb) -> std::function<void(void *builder)> { | 144 | addWriteMapping(T::name, [f](const QVariant &value, flatbuffers::FlatBufferBuilder &fbb) -> std::function<void(void *builder)> { |
diff --git a/common/synchronizer.cpp b/common/synchronizer.cpp index fa16002..1a5810d 100644 --- a/common/synchronizer.cpp +++ b/common/synchronizer.cpp | |||
@@ -634,6 +634,8 @@ KAsync::Job<void> Synchronizer::replay(const QByteArray &type, const QByteArray | |||
634 | job = replay(store().readEntity<ApplicationDomain::Addressbook>(key), operation, oldRemoteId, modifiedProperties); | 634 | job = replay(store().readEntity<ApplicationDomain::Addressbook>(key), operation, oldRemoteId, modifiedProperties); |
635 | } else if (type == ApplicationDomain::getTypeName<ApplicationDomain::Event>()) { | 635 | } else if (type == ApplicationDomain::getTypeName<ApplicationDomain::Event>()) { |
636 | job = replay(store().readEntity<ApplicationDomain::Event>(key), operation, oldRemoteId, modifiedProperties); | 636 | job = replay(store().readEntity<ApplicationDomain::Event>(key), operation, oldRemoteId, modifiedProperties); |
637 | } else if (type == ApplicationDomain::getTypeName<ApplicationDomain::Todo>()) { | ||
638 | job = replay(store().readEntity<ApplicationDomain::Todo>(key), operation, oldRemoteId, modifiedProperties); | ||
637 | } else if (type == ApplicationDomain::getTypeName<ApplicationDomain::Calendar>()) { | 639 | } else if (type == ApplicationDomain::getTypeName<ApplicationDomain::Calendar>()) { |
638 | job = replay(store().readEntity<ApplicationDomain::Calendar>(key), operation, oldRemoteId, modifiedProperties); | 640 | job = replay(store().readEntity<ApplicationDomain::Calendar>(key), operation, oldRemoteId, modifiedProperties); |
639 | } else { | 641 | } else { |
@@ -697,6 +699,11 @@ KAsync::Job<QByteArray> Synchronizer::replay(const ApplicationDomain::Event &, S | |||
697 | return KAsync::null<QByteArray>(); | 699 | return KAsync::null<QByteArray>(); |
698 | } | 700 | } |
699 | 701 | ||
702 | KAsync::Job<QByteArray> Synchronizer::replay(const ApplicationDomain::Todo &, Sink::Operation, const QByteArray &, const QList<QByteArray> &) | ||
703 | { | ||
704 | return KAsync::null<QByteArray>(); | ||
705 | } | ||
706 | |||
700 | KAsync::Job<QByteArray> Synchronizer::replay(const ApplicationDomain::Calendar &, Sink::Operation, const QByteArray &, const QList<QByteArray> &) | 707 | KAsync::Job<QByteArray> Synchronizer::replay(const ApplicationDomain::Calendar &, Sink::Operation, const QByteArray &, const QList<QByteArray> &) |
701 | { | 708 | { |
702 | return KAsync::null<QByteArray>(); | 709 | return KAsync::null<QByteArray>(); |
diff --git a/common/synchronizer.h b/common/synchronizer.h index 2a3c3d8..fffd705 100644 --- a/common/synchronizer.h +++ b/common/synchronizer.h | |||
@@ -80,6 +80,7 @@ protected: | |||
80 | virtual KAsync::Job<QByteArray> replay(const Sink::ApplicationDomain::Mail &, Sink::Operation, const QByteArray &oldRemoteId, const QList<QByteArray> &); | 80 | virtual KAsync::Job<QByteArray> replay(const Sink::ApplicationDomain::Mail &, Sink::Operation, const QByteArray &oldRemoteId, const QList<QByteArray> &); |
81 | virtual KAsync::Job<QByteArray> replay(const Sink::ApplicationDomain::Folder &, Sink::Operation, const QByteArray &oldRemoteId, const QList<QByteArray> &); | 81 | virtual KAsync::Job<QByteArray> replay(const Sink::ApplicationDomain::Folder &, Sink::Operation, const QByteArray &oldRemoteId, const QList<QByteArray> &); |
82 | virtual KAsync::Job<QByteArray> replay(const Sink::ApplicationDomain::Event &, Sink::Operation, const QByteArray &oldRemoteId, const QList<QByteArray> &); | 82 | virtual KAsync::Job<QByteArray> replay(const Sink::ApplicationDomain::Event &, Sink::Operation, const QByteArray &oldRemoteId, const QList<QByteArray> &); |
83 | virtual KAsync::Job<QByteArray> replay(const Sink::ApplicationDomain::Todo &, Sink::Operation, const QByteArray &oldRemoteId, const QList<QByteArray> &); | ||
83 | virtual KAsync::Job<QByteArray> replay(const Sink::ApplicationDomain::Calendar &, Sink::Operation, const QByteArray &oldRemoteId, const QList<QByteArray> &); | 84 | virtual KAsync::Job<QByteArray> replay(const Sink::ApplicationDomain::Calendar &, Sink::Operation, const QByteArray &oldRemoteId, const QList<QByteArray> &); |
84 | protected: | 85 | protected: |
85 | QString secret() const; | 86 | QString secret() const; |
diff --git a/common/todopreprocessor.cpp b/common/todopreprocessor.cpp new file mode 100644 index 0000000..fe99953 --- /dev/null +++ b/common/todopreprocessor.cpp | |||
@@ -0,0 +1,67 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2018 Christian Mollekopf <chrigi_1@fastmail.fm> | ||
3 | * Copyright (C) 2018 Rémi Nicole <minijackson@riseup.net> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License as published by | ||
7 | * the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the | ||
17 | * Free Software Foundation, Inc., | ||
18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
19 | */ | ||
20 | |||
21 | #include "todopreprocessor.h" | ||
22 | |||
23 | #include <KCalCore/ICalFormat> | ||
24 | |||
25 | void TodoPropertyExtractor::updatedIndexedProperties(Todo &todo, const QByteArray &rawIcal) | ||
26 | { | ||
27 | auto incidence = KCalCore::ICalFormat().readIncidence(rawIcal); | ||
28 | |||
29 | if(!incidence) { | ||
30 | SinkWarning() << "Invalid ICal to process, ignoring..."; | ||
31 | return; | ||
32 | } | ||
33 | |||
34 | if(incidence->type() != KCalCore::IncidenceBase::IncidenceType::TypeTodo) { | ||
35 | SinkWarning() << "ICal to process is not of type `Todo`, ignoring..."; | ||
36 | return; | ||
37 | } | ||
38 | |||
39 | auto icalTodo = dynamic_cast<const KCalCore::Todo *>(incidence.data()); | ||
40 | // Should be guaranteed by the incidence->type() condition above. | ||
41 | Q_ASSERT(icalTodo); | ||
42 | |||
43 | SinkTrace() << "Extracting properties for todo:" << icalTodo->summary(); | ||
44 | |||
45 | todo.setExtractedUid(icalTodo->uid()); | ||
46 | todo.setExtractedSummary(icalTodo->summary()); | ||
47 | todo.setExtractedDescription(icalTodo->description()); | ||
48 | |||
49 | // Sets invalid QDateTime if not defined | ||
50 | todo.setExtractedCompletedDate(icalTodo->completed()); | ||
51 | todo.setExtractedDueDate(icalTodo->dtDue()); | ||
52 | todo.setExtractedStartDate(icalTodo->dtStart()); | ||
53 | |||
54 | todo.setExtractedStatus(icalTodo->customStatus()); | ||
55 | todo.setExtractedPriority(icalTodo->priority()); | ||
56 | todo.setExtractedCategories(icalTodo->categories()); | ||
57 | } | ||
58 | |||
59 | void TodoPropertyExtractor::newEntity(Todo &todo) | ||
60 | { | ||
61 | updatedIndexedProperties(todo, todo.getIcal()); | ||
62 | } | ||
63 | |||
64 | void TodoPropertyExtractor::modifiedEntity(const Todo &oldTodo, Todo &newTodo) | ||
65 | { | ||
66 | updatedIndexedProperties(newTodo, newTodo.getIcal()); | ||
67 | } | ||
diff --git a/common/todopreprocessor.h b/common/todopreprocessor.h new file mode 100644 index 0000000..ccb9f1a --- /dev/null +++ b/common/todopreprocessor.h | |||
@@ -0,0 +1,35 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2018 Christian Mollekopf <chrigi_1@fastmail.fm> | ||
3 | * Copyright (C) 2018 Rémi Nicole <minijackson@riseup.net> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License as published by | ||
7 | * the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the | ||
17 | * Free Software Foundation, Inc., | ||
18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
19 | */ | ||
20 | |||
21 | #include "pipeline.h" | ||
22 | #include "sink_export.h" | ||
23 | |||
24 | class SINK_EXPORT TodoPropertyExtractor : public Sink::EntityPreprocessor<Sink::ApplicationDomain::Todo> | ||
25 | { | ||
26 | using Todo = Sink::ApplicationDomain::Todo; | ||
27 | |||
28 | public: | ||
29 | virtual ~TodoPropertyExtractor() {} | ||
30 | virtual void newEntity(Todo &todo) Q_DECL_OVERRIDE; | ||
31 | virtual void modifiedEntity(const Todo &oldTodo, Todo &newTodo) Q_DECL_OVERRIDE; | ||
32 | |||
33 | private: | ||
34 | static void updatedIndexedProperties(Todo &todo, const QByteArray &rawIcal); | ||
35 | }; | ||
diff --git a/examples/caldavresource/caldavresource.cpp b/examples/caldavresource/caldavresource.cpp index d9f8c69..d33f625 100644 --- a/examples/caldavresource/caldavresource.cpp +++ b/examples/caldavresource/caldavresource.cpp | |||
@@ -25,25 +25,29 @@ | |||
25 | #include "applicationdomaintype.h" | 25 | #include "applicationdomaintype.h" |
26 | #include "domainadaptor.h" | 26 | #include "domainadaptor.h" |
27 | #include "eventpreprocessor.h" | 27 | #include "eventpreprocessor.h" |
28 | #include "todopreprocessor.h" | ||
28 | #include "facade.h" | 29 | #include "facade.h" |
29 | #include "facadefactory.h" | 30 | #include "facadefactory.h" |
30 | 31 | ||
31 | #include <KCalCore/ICalFormat> | 32 | #include <KCalCore/ICalFormat> |
32 | 33 | ||
33 | #define ENTITY_TYPE_EVENT "event" | 34 | #define ENTITY_TYPE_EVENT "event" |
35 | #define ENTITY_TYPE_TODO "todo" | ||
34 | #define ENTITY_TYPE_CALENDAR "calendar" | 36 | #define ENTITY_TYPE_CALENDAR "calendar" |
35 | 37 | ||
36 | using Sink::ApplicationDomain::getTypeName; | 38 | using Sink::ApplicationDomain::getTypeName; |
37 | 39 | ||
38 | class EventSynchronizer : public WebDavSynchronizer | 40 | class CalDAVSynchronizer : public WebDavSynchronizer |
39 | { | 41 | { |
40 | using Event = Sink::ApplicationDomain::Event; | 42 | using Event = Sink::ApplicationDomain::Event; |
43 | using Todo = Sink::ApplicationDomain::Todo; | ||
41 | using Calendar = Sink::ApplicationDomain::Calendar; | 44 | using Calendar = Sink::ApplicationDomain::Calendar; |
42 | 45 | ||
43 | public: | 46 | public: |
44 | explicit EventSynchronizer(const Sink::ResourceContext &context) | 47 | explicit CalDAVSynchronizer(const Sink::ResourceContext &context) |
45 | : WebDavSynchronizer(context, KDAV2::CalDav, getTypeName<Calendar>(), getTypeName<Event>()) | 48 | : WebDavSynchronizer(context, KDAV2::CalDav, getTypeName<Calendar>(), getTypeName<Event>()) |
46 | {} | 49 | { |
50 | } | ||
47 | 51 | ||
48 | protected: | 52 | protected: |
49 | void updateLocalCollections(KDAV2::DavCollection::List calendarList) Q_DECL_OVERRIDE | 53 | void updateLocalCollections(KDAV2::DavCollection::List calendarList) Q_DECL_OVERRIDE |
@@ -74,21 +78,27 @@ protected: | |||
74 | 78 | ||
75 | switch (incidence->type()) { | 79 | switch (incidence->type()) { |
76 | case Type::TypeEvent: { | 80 | case Type::TypeEvent: { |
77 | auto remoteEvent = dynamic_cast<const KCalCore::Event &>(*incidence); | ||
78 | |||
79 | Event localEvent; | 81 | Event localEvent; |
80 | localEvent.setIcal(ical); | 82 | localEvent.setIcal(ical); |
81 | localEvent.setCalendar(calendarLocalId); | 83 | localEvent.setCalendar(calendarLocalId); |
82 | 84 | ||
83 | SinkTrace() << "Found an event:" << localEvent.getSummary() << "with id:" << rid; | 85 | SinkTrace() << "Found an event with id:" << rid; |
84 | 86 | ||
85 | createOrModify(ENTITY_TYPE_EVENT, rid, localEvent, | 87 | createOrModify(ENTITY_TYPE_EVENT, rid, localEvent, |
86 | /* mergeCriteria = */ QHash<QByteArray, Sink::Query::Comparator>{}); | 88 | /* mergeCriteria = */ QHash<QByteArray, Sink::Query::Comparator>{}); |
87 | break; | 89 | break; |
88 | } | 90 | } |
89 | case Type::TypeTodo: | 91 | case Type::TypeTodo: { |
90 | SinkWarning() << "Unimplemented add of a 'Todo' item in the Store"; | 92 | Todo localTodo; |
93 | localTodo.setIcal(ical); | ||
94 | localTodo.setCalendar(calendarLocalId); | ||
95 | |||
96 | SinkTrace() << "Found a Todo with id:" << rid; | ||
97 | |||
98 | createOrModify(ENTITY_TYPE_TODO, rid, localTodo, | ||
99 | /* mergeCriteria = */ QHash<QByteArray, Sink::Query::Comparator>{}); | ||
91 | break; | 100 | break; |
101 | } | ||
92 | case Type::TypeJournal: | 102 | case Type::TypeJournal: |
93 | SinkWarning() << "Unimplemented add of a 'Journal' item in the Store"; | 103 | SinkWarning() << "Unimplemented add of a 'Journal' item in the Store"; |
94 | break; | 104 | break; |
@@ -108,58 +118,74 @@ protected: | |||
108 | return syncStore().resolveRemoteId(ENTITY_TYPE_CALENDAR, resourceID(calendar)); | 118 | return syncStore().resolveRemoteId(ENTITY_TYPE_CALENDAR, resourceID(calendar)); |
109 | } | 119 | } |
110 | 120 | ||
111 | KAsync::Job<QByteArray> replay(const Event &event, Sink::Operation operation, | 121 | template<typename Item> |
112 | const QByteArray &oldRemoteId, const QList<QByteArray> &changedProperties) Q_DECL_OVERRIDE | 122 | KAsync::Job<QByteArray> replayItem(const Item &localItem, Sink::Operation operation, |
123 | const QByteArray &oldRemoteId, const QList<QByteArray> &changedProperties, | ||
124 | const QByteArray &entityType) | ||
113 | { | 125 | { |
114 | SinkLog() << "Replaying event"; | 126 | SinkLog() << "Replaying" << entityType; |
115 | 127 | ||
116 | KDAV2::DavItem item; | 128 | KDAV2::DavItem remoteItem; |
117 | 129 | ||
118 | switch (operation) { | 130 | switch (operation) { |
119 | case Sink::Operation_Creation: { | 131 | case Sink::Operation_Creation: { |
120 | auto rawIcal = event.getIcal(); | 132 | auto rawIcal = localItem.getIcal(); |
121 | if(rawIcal == "") { | 133 | if (rawIcal == "") { |
122 | return KAsync::error<QByteArray>("No ICal in event for creation replay"); | 134 | return KAsync::error<QByteArray>("No ICal in item for creation replay"); |
123 | } | 135 | } |
124 | 136 | ||
125 | auto collectionId = syncStore().resolveLocalId(ENTITY_TYPE_CALENDAR, event.getCalendar()); | 137 | auto collectionId = syncStore().resolveLocalId(ENTITY_TYPE_CALENDAR, localItem.getCalendar()); |
126 | 138 | ||
127 | item.setData(rawIcal); | 139 | remoteItem.setData(rawIcal); |
128 | item.setContentType("text/calendar"); | 140 | remoteItem.setContentType("text/calendar"); |
129 | item.setUrl(urlOf(collectionId, event.getUid())); | 141 | remoteItem.setUrl(urlOf(collectionId, localItem.getUid())); |
130 | 142 | ||
131 | SinkLog() << "Creating event:" << event.getSummary(); | 143 | SinkLog() << "Creating" << entityType << ":" << localItem.getSummary(); |
132 | return createItem(item).then([item] { return resourceID(item); }); | 144 | return createItem(remoteItem).then([remoteItem] { return resourceID(remoteItem); }); |
133 | } | 145 | } |
134 | case Sink::Operation_Removal: { | 146 | case Sink::Operation_Removal: { |
135 | // We only need the URL in the DAV item for removal | 147 | // We only need the URL in the DAV item for removal |
136 | item.setUrl(urlOf(oldRemoteId)); | 148 | remoteItem.setUrl(urlOf(oldRemoteId)); |
137 | 149 | ||
138 | SinkLog() << "Removing event:" << oldRemoteId; | 150 | SinkLog() << "Removing" << entityType << ":" << oldRemoteId; |
139 | return removeItem(item).then([] { return QByteArray{}; }); | 151 | return removeItem(remoteItem).then([] { return QByteArray{}; }); |
140 | } | 152 | } |
141 | case Sink::Operation_Modification: | 153 | case Sink::Operation_Modification: |
142 | auto rawIcal = event.getIcal(); | 154 | auto rawIcal = localItem.getIcal(); |
143 | if(rawIcal == "") { | 155 | if (rawIcal == "") { |
144 | return KAsync::error<QByteArray>("No ICal in event for modification replay"); | 156 | return KAsync::error<QByteArray>("No ICal in item for modification replay"); |
145 | } | 157 | } |
146 | 158 | ||
147 | item.setData(rawIcal); | 159 | remoteItem.setData(rawIcal); |
148 | item.setContentType("text/calendar"); | 160 | remoteItem.setContentType("text/calendar"); |
149 | item.setUrl(urlOf(oldRemoteId)); | 161 | remoteItem.setUrl(urlOf(oldRemoteId)); |
150 | 162 | ||
151 | SinkLog() << "Modifying event:" << event.getSummary(); | 163 | SinkLog() << "Modifying" << entityType << ":" << localItem.getSummary(); |
152 | 164 | ||
153 | // It would be nice to check that the URL of the item hasn't | 165 | // It would be nice to check that the URL of the item hasn't |
154 | // changed and move he item if it did, but since the URL is | 166 | // changed and move he item if it did, but since the URL is |
155 | // pretty much arbitrary, whoe does that anyway? | 167 | // pretty much arbitrary, whoe does that anyway? |
156 | return modifyItem(item).then([oldRemoteId] { return oldRemoteId; }); | 168 | return modifyItem(remoteItem).then([oldRemoteId] { return oldRemoteId; }); |
157 | } | 169 | } |
158 | } | 170 | } |
159 | 171 | ||
172 | KAsync::Job<QByteArray> replay(const Event &event, Sink::Operation operation, | ||
173 | const QByteArray &oldRemoteId, const QList<QByteArray> &changedProperties) Q_DECL_OVERRIDE | ||
174 | { | ||
175 | return replayItem(event, operation, oldRemoteId, changedProperties, ENTITY_TYPE_EVENT); | ||
176 | } | ||
177 | |||
178 | KAsync::Job<QByteArray> replay(const Todo &todo, Sink::Operation operation, | ||
179 | const QByteArray &oldRemoteId, const QList<QByteArray> &changedProperties) Q_DECL_OVERRIDE | ||
180 | { | ||
181 | return replayItem(todo, operation, oldRemoteId, changedProperties, ENTITY_TYPE_TODO); | ||
182 | } | ||
183 | |||
160 | KAsync::Job<QByteArray> replay(const Calendar &calendar, Sink::Operation operation, | 184 | KAsync::Job<QByteArray> replay(const Calendar &calendar, Sink::Operation operation, |
161 | const QByteArray &oldRemoteId, const QList<QByteArray> &changedProperties) Q_DECL_OVERRIDE | 185 | const QByteArray &oldRemoteId, const QList<QByteArray> &changedProperties) Q_DECL_OVERRIDE |
162 | { | 186 | { |
187 | SinkLog() << "Replaying calendar"; | ||
188 | |||
163 | switch (operation) { | 189 | switch (operation) { |
164 | case Sink::Operation_Creation: | 190 | case Sink::Operation_Creation: |
165 | SinkWarning() << "Unimplemented replay of calendar creation"; | 191 | SinkWarning() << "Unimplemented replay of calendar creation"; |
@@ -180,19 +206,23 @@ protected: | |||
180 | CalDavResource::CalDavResource(const Sink::ResourceContext &context) | 206 | CalDavResource::CalDavResource(const Sink::ResourceContext &context) |
181 | : Sink::GenericResource(context) | 207 | : Sink::GenericResource(context) |
182 | { | 208 | { |
183 | auto synchronizer = QSharedPointer<EventSynchronizer>::create(context); | 209 | auto synchronizer = QSharedPointer<CalDAVSynchronizer>::create(context); |
184 | setupSynchronizer(synchronizer); | 210 | setupSynchronizer(synchronizer); |
185 | 211 | ||
186 | setupPreprocessors(ENTITY_TYPE_EVENT, QVector<Sink::Preprocessor*>() << new EventPropertyExtractor); | 212 | setupPreprocessors(ENTITY_TYPE_EVENT, QVector<Sink::Preprocessor *>() << new EventPropertyExtractor); |
213 | setupPreprocessors(ENTITY_TYPE_TODO, QVector<Sink::Preprocessor *>() << new TodoPropertyExtractor); | ||
187 | } | 214 | } |
188 | 215 | ||
189 | CalDavResourceFactory::CalDavResourceFactory(QObject *parent) | 216 | CalDavResourceFactory::CalDavResourceFactory(QObject *parent) |
190 | : Sink::ResourceFactory(parent, { | 217 | : Sink::ResourceFactory(parent, { |
191 | Sink::ApplicationDomain::ResourceCapabilities::Event::event, | ||
192 | Sink::ApplicationDomain::ResourceCapabilities::Event::calendar, | 218 | Sink::ApplicationDomain::ResourceCapabilities::Event::calendar, |
219 | Sink::ApplicationDomain::ResourceCapabilities::Event::event, | ||
193 | Sink::ApplicationDomain::ResourceCapabilities::Event::storage, | 220 | Sink::ApplicationDomain::ResourceCapabilities::Event::storage, |
221 | Sink::ApplicationDomain::ResourceCapabilities::Todo::todo, | ||
222 | Sink::ApplicationDomain::ResourceCapabilities::Todo::storage, | ||
194 | }) | 223 | }) |
195 | {} | 224 | { |
225 | } | ||
196 | 226 | ||
197 | Sink::Resource *CalDavResourceFactory::createResource(const Sink::ResourceContext &context) | 227 | Sink::Resource *CalDavResourceFactory::createResource(const Sink::ResourceContext &context) |
198 | { | 228 | { |
@@ -201,10 +231,12 @@ Sink::Resource *CalDavResourceFactory::createResource(const Sink::ResourceContex | |||
201 | 231 | ||
202 | using Sink::ApplicationDomain::Calendar; | 232 | using Sink::ApplicationDomain::Calendar; |
203 | using Sink::ApplicationDomain::Event; | 233 | using Sink::ApplicationDomain::Event; |
234 | using Sink::ApplicationDomain::Todo; | ||
204 | 235 | ||
205 | void CalDavResourceFactory::registerFacades(const QByteArray &resourceName, Sink::FacadeFactory &factory) | 236 | void CalDavResourceFactory::registerFacades(const QByteArray &resourceName, Sink::FacadeFactory &factory) |
206 | { | 237 | { |
207 | factory.registerFacade<Event, Sink::DefaultFacade<Event>>(resourceName); | 238 | factory.registerFacade<Event, Sink::DefaultFacade<Event>>(resourceName); |
239 | factory.registerFacade<Todo, Sink::DefaultFacade<Todo>>(resourceName); | ||
208 | factory.registerFacade<Calendar, Sink::DefaultFacade<Calendar>>(resourceName); | 240 | factory.registerFacade<Calendar, Sink::DefaultFacade<Calendar>>(resourceName); |
209 | } | 241 | } |
210 | 242 | ||
@@ -213,6 +245,7 @@ void CalDavResourceFactory::registerAdaptorFactories( | |||
213 | const QByteArray &resourceName, Sink::AdaptorFactoryRegistry ®istry) | 245 | const QByteArray &resourceName, Sink::AdaptorFactoryRegistry ®istry) |
214 | { | 246 | { |
215 | registry.registerFactory<Event, DefaultAdaptorFactory<Event>>(resourceName); | 247 | registry.registerFactory<Event, DefaultAdaptorFactory<Event>>(resourceName); |
248 | registry.registerFactory<Todo, DefaultAdaptorFactory<Todo>>(resourceName); | ||
216 | registry.registerFactory<Calendar, DefaultAdaptorFactory<Calendar>>(resourceName); | 249 | registry.registerFactory<Calendar, DefaultAdaptorFactory<Calendar>>(resourceName); |
217 | } | 250 | } |
218 | 251 | ||
diff --git a/examples/caldavresource/tests/caldavtest.cpp b/examples/caldavresource/tests/caldavtest.cpp index f9920d9..9609fa0 100644 --- a/examples/caldavresource/tests/caldavtest.cpp +++ b/examples/caldavresource/tests/caldavtest.cpp | |||
@@ -22,13 +22,15 @@ | |||
22 | using Sink::ApplicationDomain::Calendar; | 22 | using Sink::ApplicationDomain::Calendar; |
23 | using Sink::ApplicationDomain::DummyResource; | 23 | using Sink::ApplicationDomain::DummyResource; |
24 | using Sink::ApplicationDomain::Event; | 24 | using Sink::ApplicationDomain::Event; |
25 | using Sink::ApplicationDomain::Todo; | ||
25 | using Sink::ApplicationDomain::SinkResource; | 26 | using Sink::ApplicationDomain::SinkResource; |
26 | 27 | ||
27 | class CalDavTest : public QObject | 28 | class CalDavTest : public QObject |
28 | { | 29 | { |
29 | Q_OBJECT | 30 | Q_OBJECT |
30 | 31 | ||
31 | // This test assumes a calendar MyCalendar with one event in it. | 32 | // This test assumes a calendar MyCalendar with one event and one todo in |
33 | // it. | ||
32 | 34 | ||
33 | const QString baseUrl = "http://localhost/dav/calendars/users/doe"; | 35 | const QString baseUrl = "http://localhost/dav/calendars/users/doe"; |
34 | const QString username = "doe"; | 36 | const QString username = "doe"; |
@@ -47,6 +49,7 @@ class CalDavTest : public QObject | |||
47 | QByteArray mResourceInstanceIdentifier; | 49 | QByteArray mResourceInstanceIdentifier; |
48 | 50 | ||
49 | QString addedEventUid; | 51 | QString addedEventUid; |
52 | QString addedTodoUid; | ||
50 | 53 | ||
51 | private slots: | 54 | private slots: |
52 | 55 | ||
@@ -74,6 +77,7 @@ private slots: | |||
74 | VERIFYEXEC(Sink::Store::synchronize(Sink::Query().resourceFilter(mResourceInstanceIdentifier))); | 77 | VERIFYEXEC(Sink::Store::synchronize(Sink::Query().resourceFilter(mResourceInstanceIdentifier))); |
75 | // Check in the logs that it doesn't synchronize events again because same CTag | 78 | // Check in the logs that it doesn't synchronize events again because same CTag |
76 | VERIFYEXEC(Sink::Store::synchronize(Sink::Query().resourceFilter(mResourceInstanceIdentifier))); | 79 | VERIFYEXEC(Sink::Store::synchronize(Sink::Query().resourceFilter(mResourceInstanceIdentifier))); |
80 | VERIFYEXEC(Sink::ResourceControl::flushMessageQueue(mResourceInstanceIdentifier)); | ||
77 | } | 81 | } |
78 | 82 | ||
79 | void testSyncCalEmpty() | 83 | void testSyncCalEmpty() |
@@ -83,7 +87,11 @@ private slots: | |||
83 | 87 | ||
84 | auto eventJob = Sink::Store::fetchAll<Event>(Sink::Query().request<Event::Uid>()) | 88 | auto eventJob = Sink::Store::fetchAll<Event>(Sink::Query().request<Event::Uid>()) |
85 | .then([](const QList<Event::Ptr> &events) { QCOMPARE(events.size(), 1); }); | 89 | .then([](const QList<Event::Ptr> &events) { QCOMPARE(events.size(), 1); }); |
90 | auto todoJob = Sink::Store::fetchAll<Todo>(Sink::Query().request<Todo::Uid>()) | ||
91 | .then([](const QList<Todo::Ptr> &todos) { QCOMPARE(todos.size(), 1); }); | ||
92 | |||
86 | VERIFYEXEC(eventJob); | 93 | VERIFYEXEC(eventJob); |
94 | VERIFYEXEC(todoJob); | ||
87 | 95 | ||
88 | auto calendarJob = Sink::Store::fetchAll<Calendar>(Sink::Query().request<Calendar::Name>()) | 96 | auto calendarJob = Sink::Store::fetchAll<Calendar>(Sink::Query().request<Calendar::Name>()) |
89 | .then([](const QList<Calendar::Ptr> &calendars) { | 97 | .then([](const QList<Calendar::Ptr> &calendars) { |
@@ -136,6 +144,44 @@ private slots: | |||
136 | VERIFYEXEC(verifyEventJob); | 144 | VERIFYEXEC(verifyEventJob); |
137 | } | 145 | } |
138 | 146 | ||
147 | void testAddTodo() | ||
148 | { | ||
149 | VERIFYEXEC(Sink::Store::synchronize(Sink::Query().resourceFilter(mResourceInstanceIdentifier))); | ||
150 | VERIFYEXEC(Sink::ResourceControl::flushMessageQueue(mResourceInstanceIdentifier)); | ||
151 | |||
152 | auto job = Sink::Store::fetchOne<Calendar>({}).exec(); | ||
153 | job.waitForFinished(); | ||
154 | QVERIFY2(!job.errorCode(), "Fetching Calendar failed"); | ||
155 | auto calendar = job.value(); | ||
156 | |||
157 | auto todo = QSharedPointer<KCalCore::Todo>::create(); | ||
158 | todo->setSummary("Hello"); | ||
159 | todo->setDtStart(QDateTime::currentDateTime()); | ||
160 | todo->setCreated(QDateTime::currentDateTime()); | ||
161 | addedTodoUid = QUuid::createUuid().toString(); | ||
162 | todo->setUid(addedTodoUid); | ||
163 | |||
164 | auto ical = KCalCore::ICalFormat().toICalString(todo); | ||
165 | Todo sinkTodo(mResourceInstanceIdentifier); | ||
166 | sinkTodo.setIcal(ical.toUtf8()); | ||
167 | sinkTodo.setCalendar(calendar); | ||
168 | |||
169 | SinkLog() << "Adding todo"; | ||
170 | VERIFYEXEC(Sink::Store::create(sinkTodo)); | ||
171 | VERIFYEXEC(Sink::ResourceControl::flushReplayQueue(mResourceInstanceIdentifier)); | ||
172 | |||
173 | auto verifyTodoCountJob = | ||
174 | Sink::Store::fetchAll<Todo>(Sink::Query().request<Todo::Uid>()).then([](const QList<Todo::Ptr> &todos) { | ||
175 | QCOMPARE(todos.size(), 2); | ||
176 | }); | ||
177 | VERIFYEXEC(verifyTodoCountJob); | ||
178 | |||
179 | auto verifyTodoJob = | ||
180 | Sink::Store::fetchOne<Todo>(Sink::Query().filter("uid", Sink::Query::Comparator(addedTodoUid))) | ||
181 | .then([](const Todo &todo) { QCOMPARE(todo.getSummary(), {"Hello"}); }); | ||
182 | VERIFYEXEC(verifyTodoJob); | ||
183 | } | ||
184 | |||
139 | void testModifyEvent() | 185 | void testModifyEvent() |
140 | { | 186 | { |
141 | VERIFYEXEC(Sink::Store::synchronize(Sink::Query().resourceFilter(mResourceInstanceIdentifier))); | 187 | VERIFYEXEC(Sink::Store::synchronize(Sink::Query().resourceFilter(mResourceInstanceIdentifier))); |
@@ -173,6 +219,43 @@ private slots: | |||
173 | VERIFYEXEC(verifyEventJob); | 219 | VERIFYEXEC(verifyEventJob); |
174 | } | 220 | } |
175 | 221 | ||
222 | void testModifyTodo() | ||
223 | { | ||
224 | VERIFYEXEC(Sink::Store::synchronize(Sink::Query().resourceFilter(mResourceInstanceIdentifier))); | ||
225 | VERIFYEXEC(Sink::ResourceControl::flushMessageQueue(mResourceInstanceIdentifier)); | ||
226 | |||
227 | auto job = Sink::Store::fetchOne<Todo>( | ||
228 | Sink::Query().filter("uid", Sink::Query::Comparator(addedTodoUid))) | ||
229 | .exec(); | ||
230 | job.waitForFinished(); | ||
231 | QVERIFY2(!job.errorCode(), "Fetching Todo failed"); | ||
232 | auto todo = job.value(); | ||
233 | |||
234 | auto incidence = KCalCore::ICalFormat().readIncidence(todo.getIcal()); | ||
235 | auto caltodo = incidence.dynamicCast<KCalCore::Todo>(); | ||
236 | QVERIFY2(caltodo, "Cannot convert to KCalCore todo"); | ||
237 | |||
238 | caltodo->setSummary("Hello World!"); | ||
239 | auto dummy = QSharedPointer<KCalCore::Todo>(caltodo); | ||
240 | auto newical = KCalCore::ICalFormat().toICalString(dummy); | ||
241 | |||
242 | todo.setIcal(newical.toUtf8()); | ||
243 | |||
244 | VERIFYEXEC(Sink::Store::modify(todo)); | ||
245 | |||
246 | VERIFYEXEC(Sink::Store::synchronize(Sink::Query().resourceFilter(mResourceInstanceIdentifier))); | ||
247 | VERIFYEXEC(Sink::ResourceControl::flushMessageQueue(mResourceInstanceIdentifier)); | ||
248 | |||
249 | auto verifyTodoCountJob = Sink::Store::fetchAll<Todo>({}).then( | ||
250 | [](const QList<Todo::Ptr> &todos) { QCOMPARE(todos.size(), 2); }); | ||
251 | VERIFYEXEC(verifyTodoCountJob); | ||
252 | |||
253 | auto verifyTodoJob = | ||
254 | Sink::Store::fetchOne<Todo>(Sink::Query().filter("uid", Sink::Query::Comparator(addedTodoUid))) | ||
255 | .then([](const Todo &todo) { QCOMPARE(todo.getSummary(), {"Hello World!"}); }); | ||
256 | VERIFYEXEC(verifyTodoJob); | ||
257 | } | ||
258 | |||
176 | void testSneakyModifyEvent() | 259 | void testSneakyModifyEvent() |
177 | { | 260 | { |
178 | VERIFYEXEC(Sink::Store::synchronize(Sink::Query().resourceFilter(mResourceInstanceIdentifier))); | 261 | VERIFYEXEC(Sink::Store::synchronize(Sink::Query().resourceFilter(mResourceInstanceIdentifier))); |
@@ -180,7 +263,6 @@ private slots: | |||
180 | 263 | ||
181 | // Change the item without sink's knowledge | 264 | // Change the item without sink's knowledge |
182 | { | 265 | { |
183 | qWarning() << 1; | ||
184 | auto collection = ([this]() -> KDAV2::DavCollection { | 266 | auto collection = ([this]() -> KDAV2::DavCollection { |
185 | QUrl url(baseUrl); | 267 | QUrl url(baseUrl); |
186 | url.setUserName(username); | 268 | url.setUserName(username); |
@@ -212,22 +294,17 @@ private slots: | |||
212 | return itemFetchJob.item(); | 294 | return itemFetchJob.item(); |
213 | })(); | 295 | })(); |
214 | 296 | ||
215 | qWarning() << 3; | ||
216 | auto incidence = KCalCore::ICalFormat().readIncidence(davitem.data()); | 297 | auto incidence = KCalCore::ICalFormat().readIncidence(davitem.data()); |
217 | auto calevent = incidence.dynamicCast<KCalCore::Event>(); | 298 | auto calevent = incidence.dynamicCast<KCalCore::Event>(); |
218 | QVERIFY2(calevent, "Cannot convert to KCalCore event"); | 299 | QVERIFY2(calevent, "Cannot convert to KCalCore event"); |
219 | 300 | ||
220 | qWarning() << 4; | ||
221 | calevent->setSummary("Manual Hello World!"); | 301 | calevent->setSummary("Manual Hello World!"); |
222 | auto newical = KCalCore::ICalFormat().toICalString(calevent); | 302 | auto newical = KCalCore::ICalFormat().toICalString(calevent); |
223 | 303 | ||
224 | qWarning() << 5; | ||
225 | davitem.setData(newical.toUtf8()); | 304 | davitem.setData(newical.toUtf8()); |
226 | KDAV2::DavItemModifyJob itemModifyJob(davitem); | 305 | KDAV2::DavItemModifyJob itemModifyJob(davitem); |
227 | itemModifyJob.exec(); | 306 | itemModifyJob.exec(); |
228 | QVERIFY2(itemModifyJob.error() == 0, "Cannot modify item"); | 307 | QVERIFY2(itemModifyJob.error() == 0, "Cannot modify item"); |
229 | |||
230 | qWarning() << 6; | ||
231 | } | 308 | } |
232 | 309 | ||
233 | // Try to change the item with sink | 310 | // Try to change the item with sink |
@@ -274,6 +351,26 @@ private slots: | |||
274 | [](const QList<Event::Ptr> &events) { QCOMPARE(events.size(), 1); }); | 351 | [](const QList<Event::Ptr> &events) { QCOMPARE(events.size(), 1); }); |
275 | VERIFYEXEC(verifyEventCountJob); | 352 | VERIFYEXEC(verifyEventCountJob); |
276 | } | 353 | } |
354 | |||
355 | void testRemoveTodo() | ||
356 | { | ||
357 | VERIFYEXEC(Sink::Store::synchronize(Sink::Query().resourceFilter(mResourceInstanceIdentifier))); | ||
358 | VERIFYEXEC(Sink::ResourceControl::flushMessageQueue(mResourceInstanceIdentifier)); | ||
359 | |||
360 | auto job = Sink::Store::fetchOne<Todo>( | ||
361 | Sink::Query().filter("uid", Sink::Query::Comparator(addedTodoUid))) | ||
362 | .exec(); | ||
363 | job.waitForFinished(); | ||
364 | QVERIFY2(!job.errorCode(), "Fetching Todo failed"); | ||
365 | auto todo = job.value(); | ||
366 | |||
367 | VERIFYEXEC(Sink::Store::remove(todo)); | ||
368 | VERIFYEXEC(Sink::ResourceControl::flushReplayQueue(mResourceInstanceIdentifier)); | ||
369 | |||
370 | auto verifyTodoCountJob = Sink::Store::fetchAll<Todo>({}).then( | ||
371 | [](const QList<Todo::Ptr> &todos) { QCOMPARE(todos.size(), 1); }); | ||
372 | VERIFYEXEC(verifyTodoCountJob); | ||
373 | } | ||
277 | }; | 374 | }; |
278 | 375 | ||
279 | QTEST_MAIN(CalDavTest) | 376 | QTEST_MAIN(CalDavTest) |