summaryrefslogtreecommitdiffstats
path: root/common/clientapi.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'common/clientapi.cpp')
-rw-r--r--common/clientapi.cpp141
1 files changed, 140 insertions, 1 deletions
diff --git a/common/clientapi.cpp b/common/clientapi.cpp
index e7ca99d..824ef19 100644
--- a/common/clientapi.cpp
+++ b/common/clientapi.cpp
@@ -25,6 +25,7 @@
25#include <QEventLoop> 25#include <QEventLoop>
26#include <QAbstractItemModel> 26#include <QAbstractItemModel>
27#include <QDir> 27#include <QDir>
28#include <QUuid>
28#include <functional> 29#include <functional>
29#include <memory> 30#include <memory>
30 31
@@ -204,7 +205,7 @@ KAsync::Job<void> Store::synchronize(const Akonadi2::Query &query)
204 Trace() << "Synchronizing " << resource; 205 Trace() << "Synchronizing " << resource;
205 auto resourceAccess = QSharedPointer<Akonadi2::ResourceAccess>::create(resource); 206 auto resourceAccess = QSharedPointer<Akonadi2::ResourceAccess>::create(resource);
206 resourceAccess->open(); 207 resourceAccess->open();
207 resourceAccess->synchronizeResource(query.syncOnDemand, query.processAll).then<void>([&future, resourceAccess]() { 208 resourceAccess->synchronizeResource(true, false).then<void>([&future, resourceAccess]() {
208 future.setFinished(); 209 future.setFinished();
209 }).exec(); 210 }).exec();
210 }) 211 })
@@ -212,10 +213,148 @@ KAsync::Job<void> Store::synchronize(const Akonadi2::Query &query)
212 .template then<void>([](){}); 213 .template then<void>([](){});
213} 214}
214 215
216KAsync::Job<void> Store::flushMessageQueue(const QByteArrayList &resourceIdentifier)
217{
218 Trace() << "flushMessageQueue" << resourceIdentifier;
219 return KAsync::iterate(resourceIdentifier)
220 .template each<void, QByteArray>([](const QByteArray &resource, KAsync::Future<void> &future) {
221 Trace() << "Flushing message queue " << resource;
222 auto resourceAccess = QSharedPointer<Akonadi2::ResourceAccess>::create(resource);
223 resourceAccess->open();
224 resourceAccess->synchronizeResource(false, true).then<void>([&future, resourceAccess]() {
225 future.setFinished();
226 }).exec();
227 })
228 //FIXME JOBAPI this is only required because we don't care about the return value of each (and each shouldn't even have a return value)
229 .template then<void>([](){});
230}
231
232KAsync::Job<void> Store::flushReplayQueue(const QByteArrayList &resourceIdentifier)
233{
234 return flushMessageQueue(resourceIdentifier);
235}
236
237template <class DomainType>
238KAsync::Job<DomainType> Store::fetchOne(const Akonadi2::Query &query)
239{
240 return KAsync::start<DomainType>([query](KAsync::Future<DomainType> &future) {
241 //FIXME We could do this more elegantly if composed jobs would have the correct type (In that case we'd simply return the value from then continuation, and could avoid the outer job entirely)
242 fetch<DomainType>(query, 1)
243 .template then<void, QList<typename DomainType::Ptr> >([&future](const QList<typename DomainType::Ptr> &list){
244 future.setValue(*list.first());
245 future.setFinished();
246 }, [&future](int errorCode, const QString &errorMessage) {
247 future.setError(errorCode, errorMessage);
248 future.setFinished();
249 }).exec();
250 });
251}
252
253template <class DomainType>
254KAsync::Job<QList<typename DomainType::Ptr> > Store::fetchAll(const Akonadi2::Query &query)
255{
256 return fetch<DomainType>(query);
257}
258
259template <class DomainType>
260KAsync::Job<QList<typename DomainType::Ptr> > Store::fetch(const Akonadi2::Query &query, int minimumAmount)
261{
262 auto model = loadModel<DomainType>(query);
263 auto list = QSharedPointer<QList<typename DomainType::Ptr> >::create();
264 auto context = QSharedPointer<QObject>::create();
265 return KAsync::start<QList<typename DomainType::Ptr> >([model, list, context, minimumAmount](KAsync::Future<QList<typename DomainType::Ptr> > &future) {
266 if (model->rowCount() >= 1) {
267 for (int i = 0; i < model->rowCount(); i++) {
268 list->append(model->index(i, 0, QModelIndex()).data(Akonadi2::Store::DomainObjectRole).template value<typename DomainType::Ptr>());
269 }
270 } else {
271 QObject::connect(model.data(), &QAbstractItemModel::rowsInserted, context.data(), [model, &future, list](const QModelIndex &index, int start, int end) {
272 for (int i = start; i <= end; i++) {
273 list->append(model->index(i, 0, QModelIndex()).data(Akonadi2::Store::DomainObjectRole).template value<typename DomainType::Ptr>());
274 }
275 });
276 QObject::connect(model.data(), &QAbstractItemModel::dataChanged, context.data(), [model, &future, list, minimumAmount](const QModelIndex &, const QModelIndex &, const QVector<int> &roles) {
277 if (roles.contains(ModelResult<DomainType, typename DomainType::Ptr>::ChildrenFetchedRole)) {
278 if (list->size() < minimumAmount) {
279 future.setError(1, "Not enough values.");
280 } else {
281 future.setValue(*list);
282 }
283 future.setFinished();
284 }
285 });
286 }
287 if (model->data(QModelIndex(), ModelResult<DomainType, typename DomainType::Ptr>::ChildrenFetchedRole).toBool()) {
288 if (list->size() < minimumAmount) {
289 future.setError(1, "Not enough values.");
290 } else {
291 future.setValue(*list);
292 }
293 future.setFinished();
294 }
295 });
296}
297
298template <class DomainType>
299KAsync::Job<void> Resources::inspect(const Inspection &inspectionCommand)
300{
301 auto resource = inspectionCommand.resourceIdentifier;
302
303 Trace() << "Sending inspection " << resource;
304 auto resourceAccess = QSharedPointer<Akonadi2::ResourceAccess>::create(resource);
305 resourceAccess->open();
306 auto notifier = QSharedPointer<Akonadi2::Notifier>::create(resourceAccess);
307 auto id = QUuid::createUuid().toByteArray();
308 return resourceAccess->sendInspectionCommand(id, ApplicationDomain::getTypeName<DomainType>(), inspectionCommand.entityIdentifier, inspectionCommand.property, inspectionCommand.expectedValue)
309 .template then<void>([resourceAccess, notifier, id](KAsync::Future<void> &future) {
310 notifier->registerHandler([&future, id](const Notification &notification) {
311 if (notification.id == id) {
312 if (notification.code) {
313 future.setError(-1, "Inspection returned an error: " + notification.message);
314 } else {
315 future.setFinished();
316 }
317 }
318 });
319 });
320}
321
322class Akonadi2::Notifier::Private {
323public:
324 Private()
325 : context(new QObject)
326 {
327
328 }
329 QList<QSharedPointer<ResourceAccess> > resourceAccess;
330 QList<std::function<void(const Notification &)> > handler;
331 QSharedPointer<QObject> context;
332};
333
334Notifier::Notifier(const QSharedPointer<ResourceAccess> &resourceAccess)
335 : d(new Akonadi2::Notifier::Private)
336{
337 QObject::connect(resourceAccess.data(), &ResourceAccess::notification, d->context.data(), [this](const Notification &notification) {
338 for (const auto &handler : d->handler) {
339 handler(notification);
340 }
341 });
342 d->resourceAccess << resourceAccess;
343}
344
345void Notifier::registerHandler(std::function<void(const Notification &)> handler)
346{
347 d->handler << handler;
348}
349
215#define REGISTER_TYPE(T) template KAsync::Job<void> Store::remove<T>(const T &domainObject); \ 350#define REGISTER_TYPE(T) template KAsync::Job<void> Store::remove<T>(const T &domainObject); \
216 template KAsync::Job<void> Store::create<T>(const T &domainObject); \ 351 template KAsync::Job<void> Store::create<T>(const T &domainObject); \
217 template KAsync::Job<void> Store::modify<T>(const T &domainObject); \ 352 template KAsync::Job<void> Store::modify<T>(const T &domainObject); \
218 template QSharedPointer<QAbstractItemModel> Store::loadModel<T>(Query query); \ 353 template QSharedPointer<QAbstractItemModel> Store::loadModel<T>(Query query); \
354 template KAsync::Job<void> Resources::inspect<T>(const Inspection &); \
355 template KAsync::Job<T> Store::fetchOne<T>(const Query &); \
356 template KAsync::Job<QList<T::Ptr> > Store::fetchAll<T>(const Query &); \
357 template KAsync::Job<QList<T::Ptr> > Store::fetch<T>(const Query &, int); \
219 358
220REGISTER_TYPE(ApplicationDomain::Event); 359REGISTER_TYPE(ApplicationDomain::Event);
221REGISTER_TYPE(ApplicationDomain::Mail); 360REGISTER_TYPE(ApplicationDomain::Mail);