summaryrefslogtreecommitdiffstats
path: root/examples
diff options
context:
space:
mode:
authorRémi Nicole <nicole@kolabsystems.com>2018-05-03 09:45:45 +0200
committerChristian Mollekopf <chrigi_1@fastmail.fm>2018-05-03 09:47:35 +0200
commit41ba42150d4232807299214a6fcfa44c669489b0 (patch)
tree117ff2c2afbc5fa2170c7d56a55f80b7811be235 /examples
parent7a166895a54c4037749229b9ec9d0c90d60987b5 (diff)
downloadsink-41ba42150d4232807299214a6fcfa44c669489b0.tar.gz
sink-41ba42150d4232807299214a6fcfa44c669489b0.zip
Implement replaying CalDAV events and calendars
Summary: Notes: - For calendars, only removal is implemented because: - There is no DavCollectionCreateJob, possibly because there can't be an empty DAV collection - DavCollectionModifyJob only allows modifying "properties", which we don't use (except for the name, if the name is considered a property) - Currently, modifying an item with Sink overrides the one on the server, even if the store is not up-to-date Reviewers: cmollekopf Tags: #sink Differential Revision: https://phabricator.kde.org/D12611
Diffstat (limited to 'examples')
-rw-r--r--examples/caldavresource/caldavresource.cpp68
-rw-r--r--examples/caldavresource/tests/caldavtest.cpp259
-rw-r--r--examples/webdavcommon/webdav.cpp67
-rw-r--r--examples/webdavcommon/webdav.h39
4 files changed, 398 insertions, 35 deletions
diff --git a/examples/caldavresource/caldavresource.cpp b/examples/caldavresource/caldavresource.cpp
index 6bf1a27..d9f8c69 100644
--- a/examples/caldavresource/caldavresource.cpp
+++ b/examples/caldavresource/caldavresource.cpp
@@ -107,6 +107,74 @@ protected:
107 { 107 {
108 return syncStore().resolveRemoteId(ENTITY_TYPE_CALENDAR, resourceID(calendar)); 108 return syncStore().resolveRemoteId(ENTITY_TYPE_CALENDAR, resourceID(calendar));
109 } 109 }
110
111 KAsync::Job<QByteArray> replay(const Event &event, Sink::Operation operation,
112 const QByteArray &oldRemoteId, const QList<QByteArray> &changedProperties) Q_DECL_OVERRIDE
113 {
114 SinkLog() << "Replaying event";
115
116 KDAV2::DavItem item;
117
118 switch (operation) {
119 case Sink::Operation_Creation: {
120 auto rawIcal = event.getIcal();
121 if(rawIcal == "") {
122 return KAsync::error<QByteArray>("No ICal in event for creation replay");
123 }
124
125 auto collectionId = syncStore().resolveLocalId(ENTITY_TYPE_CALENDAR, event.getCalendar());
126
127 item.setData(rawIcal);
128 item.setContentType("text/calendar");
129 item.setUrl(urlOf(collectionId, event.getUid()));
130
131 SinkLog() << "Creating event:" << event.getSummary();
132 return createItem(item).then([item] { return resourceID(item); });
133 }
134 case Sink::Operation_Removal: {
135 // We only need the URL in the DAV item for removal
136 item.setUrl(urlOf(oldRemoteId));
137
138 SinkLog() << "Removing event:" << oldRemoteId;
139 return removeItem(item).then([] { return QByteArray{}; });
140 }
141 case Sink::Operation_Modification:
142 auto rawIcal = event.getIcal();
143 if(rawIcal == "") {
144 return KAsync::error<QByteArray>("No ICal in event for modification replay");
145 }
146
147 item.setData(rawIcal);
148 item.setContentType("text/calendar");
149 item.setUrl(urlOf(oldRemoteId));
150
151 SinkLog() << "Modifying event:" << event.getSummary();
152
153 // 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
155 // pretty much arbitrary, whoe does that anyway?
156 return modifyItem(item).then([oldRemoteId] { return oldRemoteId; });
157 }
158 }
159
160 KAsync::Job<QByteArray> replay(const Calendar &calendar, Sink::Operation operation,
161 const QByteArray &oldRemoteId, const QList<QByteArray> &changedProperties) Q_DECL_OVERRIDE
162 {
163 switch (operation) {
164 case Sink::Operation_Creation:
165 SinkWarning() << "Unimplemented replay of calendar creation";
166 break;
167 case Sink::Operation_Removal:
168 SinkLog() << "Replaying calendar removal";
169 removeCollection(urlOf(oldRemoteId));
170 break;
171 case Sink::Operation_Modification:
172 SinkWarning() << "Unimplemented replay of calendar modification";
173 break;
174 }
175
176 return KAsync::null<QByteArray>();
177 }
110}; 178};
111 179
112CalDavResource::CalDavResource(const Sink::ResourceContext &context) 180CalDavResource::CalDavResource(const Sink::ResourceContext &context)
diff --git a/examples/caldavresource/tests/caldavtest.cpp b/examples/caldavresource/tests/caldavtest.cpp
index 584e288..f9920d9 100644
--- a/examples/caldavresource/tests/caldavtest.cpp
+++ b/examples/caldavresource/tests/caldavtest.cpp
@@ -1,5 +1,14 @@
1#include <QtTest> 1#include <QtTest>
2 2
3#include <KDAV2/DavCollectionsFetchJob>
4#include <KDAV2/DavItemFetchJob>
5#include <KDAV2/DavItemModifyJob>
6#include <KDAV2/DavItemsListJob>
7#include <KDAV2/EtagCache>
8
9#include <KCalCore/Event>
10#include <KCalCore/ICalFormat>
11
3#include "../caldavresource.h" 12#include "../caldavresource.h"
4 13
5#include "common/resourcecontrol.h" 14#include "common/resourcecontrol.h"
@@ -8,6 +17,8 @@
8#include "common/test.h" 17#include "common/test.h"
9#include "tests/testutils.h" 18#include "tests/testutils.h"
10 19
20#include <algorithm>
21
11using Sink::ApplicationDomain::Calendar; 22using Sink::ApplicationDomain::Calendar;
12using Sink::ApplicationDomain::DummyResource; 23using Sink::ApplicationDomain::DummyResource;
13using Sink::ApplicationDomain::Event; 24using Sink::ApplicationDomain::Event;
@@ -17,19 +28,26 @@ class CalDavTest : public QObject
17{ 28{
18 Q_OBJECT 29 Q_OBJECT
19 30
31 // This test assumes a calendar MyCalendar with one event in it.
32
33 const QString baseUrl = "http://localhost/dav/calendars/users/doe";
34 const QString username = "doe";
35 const QString password = "doe";
36
20 SinkResource createResource() 37 SinkResource createResource()
21 { 38 {
22 auto resource = Sink::ApplicationDomain::CalDavResource::create("account1"); 39 auto resource = Sink::ApplicationDomain::CalDavResource::create("account1");
23 resource.setProperty("server", "http://localhost/dav/calendars/users/doe"); 40 resource.setProperty("server", baseUrl);
24 resource.setProperty("username", "doe"); 41 resource.setProperty("username", username);
25 Sink::SecretStore::instance().insert(resource.identifier(), "doe"); 42 Sink::SecretStore::instance().insert(resource.identifier(), password);
26 resource.setProperty("testmode", true); 43 resource.setProperty("testmode", true);
27 return resource; 44 return resource;
28 } 45 }
29 46
30
31 QByteArray mResourceInstanceIdentifier; 47 QByteArray mResourceInstanceIdentifier;
32 48
49 QString addedEventUid;
50
33private slots: 51private slots:
34 52
35 void initTestCase() 53 void initTestCase()
@@ -51,34 +69,211 @@ private slots:
51 VERIFYEXEC(Sink::ResourceControl::start(mResourceInstanceIdentifier)); 69 VERIFYEXEC(Sink::ResourceControl::start(mResourceInstanceIdentifier));
52 } 70 }
53 71
54 // void testSyncCal() 72 void testSyncCal()
55 // { 73 {
56 // VERIFYEXEC(Sink::Store::synchronize(Sink::Query().resourceFilter(mResourceInstanceIdentifier))); 74 VERIFYEXEC(Sink::Store::synchronize(Sink::Query().resourceFilter(mResourceInstanceIdentifier)));
57 // // Check in the logs that it doesn't synchronize events again because same CTag 75 // Check in the logs that it doesn't synchronize events again because same CTag
58 // VERIFYEXEC(Sink::Store::synchronize(Sink::Query().resourceFilter(mResourceInstanceIdentifier))); 76 VERIFYEXEC(Sink::Store::synchronize(Sink::Query().resourceFilter(mResourceInstanceIdentifier)));
59 // } 77 }
60 78
61 // void testSyncCalEmpty() 79 void testSyncCalEmpty()
62 // { 80 {
63 // VERIFYEXEC(Sink::Store::synchronize(Sink::Query().resourceFilter(mResourceInstanceIdentifier))); 81 VERIFYEXEC(Sink::Store::synchronize(Sink::Query().resourceFilter(mResourceInstanceIdentifier)));
64 82 VERIFYEXEC(Sink::ResourceControl::flushMessageQueue(mResourceInstanceIdentifier));
65 // auto eventJob = 83
66 // Sink::Store::fetchAll<Event>(Sink::Query().request<Event::Uid>()).then([](const QList<Event::Ptr> &events) { 84 auto eventJob = Sink::Store::fetchAll<Event>(Sink::Query().request<Event::Uid>())
67 // QCOMPARE(events.size(), 14); 85 .then([](const QList<Event::Ptr> &events) { QCOMPARE(events.size(), 1); });
68 // }); 86 VERIFYEXEC(eventJob);
69 // VERIFYEXEC(eventJob); 87
70 88 auto calendarJob = Sink::Store::fetchAll<Calendar>(Sink::Query().request<Calendar::Name>())
71 // auto calendarJob = 89 .then([](const QList<Calendar::Ptr> &calendars) {
72 // Sink::Store::fetchAll<Calendar>(Sink::Query().request<Calendar::Name>()).then([](const QList<Calendar::Ptr> &calendars) { 90 QCOMPARE(calendars.size(), 1);
73 // QCOMPARE(calendars.size(), 2); 91 for (const auto &calendar : calendars) {
74 // for (const auto &calendar : calendars) { 92 QVERIFY(calendar->getName() == "MyCalendar");
75 // QVERIFY(calendar->getName() == "Calendar" || calendar->getName() == "Tasks"); 93 }
76 // } 94 });
77 // }); 95 VERIFYEXEC(calendarJob);
78 // VERIFYEXEC(calendarJob); 96
79 97 SinkLog() << "Finished";
80 // SinkLog() << "Finished"; 98 }
81 // } 99
100 void testAddEvent()
101 {
102 VERIFYEXEC(Sink::Store::synchronize(Sink::Query().resourceFilter(mResourceInstanceIdentifier)));
103 VERIFYEXEC(Sink::ResourceControl::flushMessageQueue(mResourceInstanceIdentifier));
104
105 auto job = Sink::Store::fetchOne<Calendar>({}).exec();
106 job.waitForFinished();
107 QVERIFY2(!job.errorCode(), "Fetching Calendar failed");
108 auto calendar = job.value();
109
110 auto event = QSharedPointer<KCalCore::Event>::create();
111 event->setSummary("Hello");
112 event->setDtStart(QDateTime::currentDateTime());
113 event->setDtEnd(QDateTime::currentDateTime().addSecs(3600));
114 event->setCreated(QDateTime::currentDateTime());
115 addedEventUid = QUuid::createUuid().toString();
116 event->setUid(addedEventUid);
117
118 auto ical = KCalCore::ICalFormat().toICalString(event);
119 Event sinkEvent(mResourceInstanceIdentifier);
120 sinkEvent.setIcal(ical.toUtf8());
121 sinkEvent.setCalendar(calendar);
122
123 SinkLog() << "Adding event";
124 VERIFYEXEC(Sink::Store::create(sinkEvent));
125 VERIFYEXEC(Sink::ResourceControl::flushReplayQueue(mResourceInstanceIdentifier));
126
127 auto verifyEventCountJob =
128 Sink::Store::fetchAll<Event>(Sink::Query().request<Event::Uid>()).then([](const QList<Event::Ptr> &events) {
129 QCOMPARE(events.size(), 2);
130 });
131 VERIFYEXEC(verifyEventCountJob);
132
133 auto verifyEventJob =
134 Sink::Store::fetchOne<Event>(Sink::Query().filter("uid", Sink::Query::Comparator(addedEventUid)))
135 .then([](const Event &event) { QCOMPARE(event.getSummary(), {"Hello"}); });
136 VERIFYEXEC(verifyEventJob);
137 }
138
139 void testModifyEvent()
140 {
141 VERIFYEXEC(Sink::Store::synchronize(Sink::Query().resourceFilter(mResourceInstanceIdentifier)));
142 VERIFYEXEC(Sink::ResourceControl::flushMessageQueue(mResourceInstanceIdentifier));
143
144 auto job = Sink::Store::fetchOne<Event>(
145 Sink::Query().filter("uid", Sink::Query::Comparator(addedEventUid)))
146 .exec();
147 job.waitForFinished();
148 QVERIFY2(!job.errorCode(), "Fetching Event failed");
149 auto event = job.value();
150
151 auto incidence = KCalCore::ICalFormat().readIncidence(event.getIcal());
152 auto calevent = incidence.dynamicCast<KCalCore::Event>();
153 QVERIFY2(calevent, "Cannot convert to KCalCore event");
154
155 calevent->setSummary("Hello World!");
156 auto dummy = QSharedPointer<KCalCore::Event>(calevent);
157 auto newical = KCalCore::ICalFormat().toICalString(dummy);
158
159 event.setIcal(newical.toUtf8());
160
161 VERIFYEXEC(Sink::Store::modify(event));
162
163 VERIFYEXEC(Sink::Store::synchronize(Sink::Query().resourceFilter(mResourceInstanceIdentifier)));
164 VERIFYEXEC(Sink::ResourceControl::flushMessageQueue(mResourceInstanceIdentifier));
165
166 auto verifyEventCountJob = Sink::Store::fetchAll<Event>({}).then(
167 [](const QList<Event::Ptr> &events) { QCOMPARE(events.size(), 2); });
168 VERIFYEXEC(verifyEventCountJob);
169
170 auto verifyEventJob =
171 Sink::Store::fetchOne<Event>(Sink::Query().filter("uid", Sink::Query::Comparator(addedEventUid)))
172 .then([](const Event &event) { QCOMPARE(event.getSummary(), {"Hello World!"}); });
173 VERIFYEXEC(verifyEventJob);
174 }
175
176 void testSneakyModifyEvent()
177 {
178 VERIFYEXEC(Sink::Store::synchronize(Sink::Query().resourceFilter(mResourceInstanceIdentifier)));
179 VERIFYEXEC(Sink::ResourceControl::flushMessageQueue(mResourceInstanceIdentifier));
180
181 // Change the item without sink's knowledge
182 {
183 qWarning() << 1;
184 auto collection = ([this]() -> KDAV2::DavCollection {
185 QUrl url(baseUrl);
186 url.setUserName(username);
187 url.setPassword(password);
188 KDAV2::DavUrl davurl(url, KDAV2::CalDav);
189 KDAV2::DavCollectionsFetchJob collectionsJob(davurl);
190 collectionsJob.exec();
191 Q_ASSERT(collectionsJob.error() == 0);
192 return collectionsJob.collections()[0];
193 })();
194
195 auto itemList = ([&collection]() -> KDAV2::DavItem::List {
196 auto cache = std::make_shared<KDAV2::EtagCache>();
197 KDAV2::DavItemsListJob itemsListJob(collection.url(), cache);
198 itemsListJob.exec();
199 Q_ASSERT(itemsListJob.error() == 0);
200 return itemsListJob.items();
201 })();
202 auto hollowDavItemIt =
203 std::find_if(itemList.begin(), itemList.end(), [this](const KDAV2::DavItem &item) {
204 return item.url().url().path().endsWith(addedEventUid);
205 });
206
207 auto davitem = ([this, &collection, &hollowDavItemIt]() -> KDAV2::DavItem {
208 QString itemUrl = collection.url().url().toEncoded() + addedEventUid;
209 KDAV2::DavItemFetchJob itemFetchJob(*hollowDavItemIt);
210 itemFetchJob.exec();
211 Q_ASSERT(itemFetchJob.error() == 0);
212 return itemFetchJob.item();
213 })();
214
215 qWarning() << 3;
216 auto incidence = KCalCore::ICalFormat().readIncidence(davitem.data());
217 auto calevent = incidence.dynamicCast<KCalCore::Event>();
218 QVERIFY2(calevent, "Cannot convert to KCalCore event");
219
220 qWarning() << 4;
221 calevent->setSummary("Manual Hello World!");
222 auto newical = KCalCore::ICalFormat().toICalString(calevent);
223
224 qWarning() << 5;
225 davitem.setData(newical.toUtf8());
226 KDAV2::DavItemModifyJob itemModifyJob(davitem);
227 itemModifyJob.exec();
228 QVERIFY2(itemModifyJob.error() == 0, "Cannot modify item");
229
230 qWarning() << 6;
231 }
232
233 // Try to change the item with sink
234 {
235 auto job = Sink::Store::fetchOne<Event>(
236 Sink::Query().filter("uid", Sink::Query::Comparator(addedEventUid)))
237 .exec();
238 job.waitForFinished();
239 QVERIFY2(!job.errorCode(), "Fetching Event failed");
240 auto event = job.value();
241
242 auto incidence = KCalCore::ICalFormat().readIncidence(event.getIcal());
243 auto calevent = incidence.dynamicCast<KCalCore::Event>();
244 QVERIFY2(calevent, "Cannot convert to KCalCore event");
245
246 calevent->setSummary("Sink Hello World!");
247 auto dummy = QSharedPointer<KCalCore::Event>(calevent);
248 auto newical = KCalCore::ICalFormat().toICalString(dummy);
249
250 event.setIcal(newical.toUtf8());
251
252 // TODO: make that fail
253 VERIFYEXEC(Sink::Store::modify(event));
254 VERIFYEXEC(Sink::ResourceControl::flushReplayQueue(mResourceInstanceIdentifier));
255 }
256 }
257
258 void testRemoveEvent()
259 {
260 VERIFYEXEC(Sink::Store::synchronize(Sink::Query().resourceFilter(mResourceInstanceIdentifier)));
261 VERIFYEXEC(Sink::ResourceControl::flushMessageQueue(mResourceInstanceIdentifier));
262
263 auto job = Sink::Store::fetchOne<Event>(
264 Sink::Query().filter("uid", Sink::Query::Comparator(addedEventUid)))
265 .exec();
266 job.waitForFinished();
267 QVERIFY2(!job.errorCode(), "Fetching Event failed");
268 auto event = job.value();
269
270 VERIFYEXEC(Sink::Store::remove(event));
271 VERIFYEXEC(Sink::ResourceControl::flushReplayQueue(mResourceInstanceIdentifier));
272
273 auto verifyEventCountJob = Sink::Store::fetchAll<Event>({}).then(
274 [](const QList<Event::Ptr> &events) { QCOMPARE(events.size(), 1); });
275 VERIFYEXEC(verifyEventCountJob);
276 }
82}; 277};
83 278
84QTEST_MAIN(CalDavTest) 279QTEST_MAIN(CalDavTest)
diff --git a/examples/webdavcommon/webdav.cpp b/examples/webdavcommon/webdav.cpp
index ad1af35..e5f4fab 100644
--- a/examples/webdavcommon/webdav.cpp
+++ b/examples/webdavcommon/webdav.cpp
@@ -22,8 +22,13 @@
22#include "applicationdomaintype.h" 22#include "applicationdomaintype.h"
23#include "resourceconfig.h" 23#include "resourceconfig.h"
24 24
25#include <KDAV2/DavCollectionDeleteJob>
26#include <KDAV2/DavCollectionModifyJob>
25#include <KDAV2/DavCollectionsFetchJob> 27#include <KDAV2/DavCollectionsFetchJob>
28#include <KDAV2/DavItemCreateJob>
29#include <KDAV2/DavItemDeleteJob>
26#include <KDAV2/DavItemFetchJob> 30#include <KDAV2/DavItemFetchJob>
31#include <KDAV2/DavItemModifyJob>
27#include <KDAV2/DavItemsListJob> 32#include <KDAV2/DavItemsListJob>
28#include <KDAV2/EtagCache> 33#include <KDAV2/EtagCache>
29 34
@@ -180,7 +185,6 @@ KAsync::Job<void> WebDavSynchronizer::synchronizeCollection(const KDAV2::DavColl
180 185
181 auto localRid = collectionLocalResourceID(collection); 186 auto localRid = collectionLocalResourceID(collection);
182 187
183 // The ETag cache is useless here, since `sinkStore()` IS the cache.
184 auto cache = std::make_shared<KDAV2::EtagCache>(); 188 auto cache = std::make_shared<KDAV2::EtagCache>();
185 auto davItemsListJob = new KDAV2::DavItemsListJob(collection.url(), std::move(cache)); 189 auto davItemsListJob = new KDAV2::DavItemsListJob(collection.url(), std::move(cache));
186 190
@@ -234,14 +238,71 @@ KAsync::Job<void> WebDavSynchronizer::synchronizeItem(const KDAV2::DavItem &item
234 }); 238 });
235} 239}
236 240
241KAsync::Job<void> WebDavSynchronizer::createItem(const KDAV2::DavItem &item)
242{
243 auto job = new KDAV2::DavItemCreateJob(item);
244 return runJob(job).then([] { SinkTrace() << "Done creating item"; });
245}
246
247KAsync::Job<void> WebDavSynchronizer::removeItem(const KDAV2::DavItem &item)
248{
249 auto job = new KDAV2::DavItemDeleteJob(item);
250 return runJob(job).then([] { SinkTrace() << "Done removing item"; });
251}
252
253KAsync::Job<void> WebDavSynchronizer::modifyItem(const KDAV2::DavItem &item)
254{
255 auto job = new KDAV2::DavItemModifyJob(item);
256 return runJob(job).then([] { SinkTrace() << "Done modifying item"; });
257}
258
259// There is no "DavCollectionCreateJob"
260/*
261KAsync::Job<void> WebDavSynchronizer::createCollection(const KDAV2::DavCollection &collection)
262{
263 auto job = new KDAV2::DavCollectionCreateJob(collection);
264 return runJob(job);
265}
266*/
267
268KAsync::Job<void> WebDavSynchronizer::removeCollection(const KDAV2::DavUrl &url)
269{
270 auto job = new KDAV2::DavCollectionDeleteJob(url);
271 return runJob(job).then([] { SinkLog() << "Done removing collection"; });
272}
273
274// Useless without using the `setProperty` method of DavCollectionModifyJob
275/*
276KAsync::Job<void> WebDavSynchronizer::modifyCollection(const KDAV2::DavUrl &url)
277{
278 auto job = new KDAV2::DavCollectionModifyJob(url);
279 return runJob(job).then([] { SinkLog() << "Done modifying collection"; });
280}
281*/
282
237QByteArray WebDavSynchronizer::resourceID(const KDAV2::DavCollection &collection) 283QByteArray WebDavSynchronizer::resourceID(const KDAV2::DavCollection &collection)
238{ 284{
239 return collection.url().toDisplayString().toUtf8(); 285 return collection.url().url().path().toUtf8();
240} 286}
241 287
242QByteArray WebDavSynchronizer::resourceID(const KDAV2::DavItem &item) 288QByteArray WebDavSynchronizer::resourceID(const KDAV2::DavItem &item)
243{ 289{
244 return item.url().toDisplayString().toUtf8(); 290 return item.url().url().path().toUtf8();
291}
292
293KDAV2::DavUrl WebDavSynchronizer::urlOf(const QByteArray &remoteId)
294{
295 auto davurl = serverUrl();
296 auto url = davurl.url();
297 url.setPath(remoteId);
298 SinkLog() << "Returning URL:" << url.toEncoded();
299 davurl.setUrl(url);
300 return davurl;
301}
302
303KDAV2::DavUrl WebDavSynchronizer::urlOf(const QByteArray &collectionRemoteId, const QString &itemPath)
304{
305 return urlOf(collectionRemoteId + "/" + itemPath.toUtf8());
245} 306}
246 307
247bool WebDavSynchronizer::unchanged(const KDAV2::DavCollection &collection) 308bool WebDavSynchronizer::unchanged(const KDAV2::DavCollection &collection)
diff --git a/examples/webdavcommon/webdav.h b/examples/webdavcommon/webdav.h
index 3a4977c..ecb6a81 100644
--- a/examples/webdavcommon/webdav.h
+++ b/examples/webdavcommon/webdav.h
@@ -35,6 +35,32 @@ public:
35 KAsync::Job<void> synchronizeWithSource(const Sink::QueryBase &query) Q_DECL_OVERRIDE; 35 KAsync::Job<void> synchronizeWithSource(const Sink::QueryBase &query) Q_DECL_OVERRIDE;
36 36
37protected: 37protected:
38
39 /**
40 * Called in a child synchronizer, when replaying a creation of an item.
41 */
42 KAsync::Job<void> createItem(const KDAV2::DavItem &);
43
44 /**
45 * Called in a child synchronizer, when replaying a removal of an item.
46 */
47 KAsync::Job<void> removeItem(const KDAV2::DavItem &);
48
49 /**
50 * Called in a child synchronizer, when replaying a modification of an item.
51 *
52 * The item to modify is chosen according to the given item's URL.
53 * The job will fail if the ETag does not match.
54 */
55 KAsync::Job<void> modifyItem(const KDAV2::DavItem &);
56
57 /**
58 * See comments of the *Item version above
59 */
60 KAsync::Job<void> createCollection(const KDAV2::DavUrl &);
61 KAsync::Job<void> removeCollection(const KDAV2::DavUrl &);
62 KAsync::Job<void> modifyCollection(const KDAV2::DavUrl &);
63
38 /** 64 /**
39 * Called with the list of discovered collections. It's purpose should be 65 * Called with the list of discovered collections. It's purpose should be
40 * adding the said collections to the store. 66 * adding the said collections to the store.
@@ -63,6 +89,19 @@ protected:
63 static QByteArray resourceID(const KDAV2::DavCollection &); 89 static QByteArray resourceID(const KDAV2::DavCollection &);
64 static QByteArray resourceID(const KDAV2::DavItem &); 90 static QByteArray resourceID(const KDAV2::DavItem &);
65 91
92 /**
93 * Used to get the url of an item / collection with the given remote ID
94 */
95 KDAV2::DavUrl urlOf(const QByteArray &remoteId);
96
97 /**
98 * Used to get the url of an item / collection with the given remote ID,
99 * and append `itemPath` to the path of the URI.
100 *
101 * Useful when adding a new item to a collection
102 */
103 KDAV2::DavUrl urlOf(const QByteArray &collectionRemoteId, const QString &itemPath);
104
66 bool unchanged(const KDAV2::DavCollection &); 105 bool unchanged(const KDAV2::DavCollection &);
67 bool unchanged(const KDAV2::DavItem &); 106 bool unchanged(const KDAV2::DavItem &);
68 107