From fd9703a6f990d965d1c7fba21fee36b2beef644e Mon Sep 17 00:00:00 2001 From: Christian Mollekopf Date: Thu, 14 Jan 2016 18:22:36 +0100 Subject: An imperative query API --- common/clientapi.cpp | 64 +++++++++++++++++++++++++++++++++++++++++++++++++ common/clientapi.h | 9 +++++++ tests/clientapitest.cpp | 20 ++++++++++++++++ 3 files changed, 93 insertions(+) diff --git a/common/clientapi.cpp b/common/clientapi.cpp index e7ca99d..2c25220 100644 --- a/common/clientapi.cpp +++ b/common/clientapi.cpp @@ -212,10 +212,74 @@ KAsync::Job Store::synchronize(const Akonadi2::Query &query) .template then([](){}); } +template +KAsync::Job Store::fetchOne(const Akonadi2::Query &query) +{ + return KAsync::start([query](KAsync::Future &future) { + //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) + fetch(query, 1) + .template then >([&future](const QList &list){ + future.setValue(*list.first()); + future.setFinished(); + }, [&future](int errorCode, const QString &errorMessage) { + future.setError(errorCode, errorMessage); + future.setFinished(); + }).exec(); + }); +} + +template +KAsync::Job > Store::fetchAll(const Akonadi2::Query &query) +{ + return fetch(query); +} + +template +KAsync::Job > Store::fetch(const Akonadi2::Query &query, int minimumAmount) +{ + auto model = loadModel(query); + auto list = QSharedPointer >::create(); + auto context = QSharedPointer::create(); + return KAsync::start >([model, list, context, minimumAmount](KAsync::Future > &future) { + if (model->rowCount() >= 1) { + for (int i = 0; i < model->rowCount(); i++) { + list->append(model->index(i, 0, QModelIndex()).data(Akonadi2::Store::DomainObjectRole).template value()); + } + } else { + QObject::connect(model.data(), &QAbstractItemModel::rowsInserted, context.data(), [model, &future, list](const QModelIndex &index, int start, int end) { + for (int i = start; i <= end; i++) { + list->append(model->index(i, 0, QModelIndex()).data(Akonadi2::Store::DomainObjectRole).template value()); + } + }); + QObject::connect(model.data(), &QAbstractItemModel::dataChanged, context.data(), [model, &future, list, minimumAmount](const QModelIndex &, const QModelIndex &, const QVector &roles) { + if (roles.contains(ModelResult::ChildrenFetchedRole)) { + if (list->size() < minimumAmount) { + future.setError(1, "Not enough values."); + } else { + future.setValue(*list); + } + future.setFinished(); + } + }); + } + if (model->data(QModelIndex(), ModelResult::ChildrenFetchedRole).toBool()) { + if (list->size() < minimumAmount) { + future.setError(1, "Not enough values."); + } else { + future.setValue(*list); + } + future.setFinished(); + } + }); +} + #define REGISTER_TYPE(T) template KAsync::Job Store::remove(const T &domainObject); \ template KAsync::Job Store::create(const T &domainObject); \ template KAsync::Job Store::modify(const T &domainObject); \ template QSharedPointer Store::loadModel(Query query); \ + template KAsync::Job Store::fetchOne(const Query &); \ + template KAsync::Job > Store::fetchAll(const Query &); \ + template KAsync::Job > Store::fetch(const Query &, int); \ REGISTER_TYPE(ApplicationDomain::Event); REGISTER_TYPE(ApplicationDomain::Mail); diff --git a/common/clientapi.h b/common/clientapi.h index 4e55432..f1c3bc6 100644 --- a/common/clientapi.h +++ b/common/clientapi.h @@ -95,6 +95,15 @@ public: * Removes a resource from disk. */ static void removeFromDisk(const QByteArray &resourceIdentifier); + + template + static KAsync::Job fetchOne(const Akonadi2::Query &query); + + template + static KAsync::Job > fetchAll(const Akonadi2::Query &query); + + template + static KAsync::Job > fetch(const Akonadi2::Query &query, int minimumAmount = 0); }; diff --git a/tests/clientapitest.cpp b/tests/clientapitest.cpp index ff79c82..5942849 100644 --- a/tests/clientapitest.cpp +++ b/tests/clientapitest.cpp @@ -279,6 +279,26 @@ private Q_SLOTS: QCOMPARE(childrenFetchedCount, 1); } + void testImperativeLoad() + { + auto facade = DummyResourceFacade::registerFacade(); + facade->results << QSharedPointer::create("resource", "id", 0, QSharedPointer::create()); + ResourceConfig::addResource("dummyresource.instance1", "dummyresource"); + + Akonadi2::Query query; + query.resources << "dummyresource.instance1"; + query.liveQuery = false; + + bool gotValue = false; + auto result = Akonadi2::Store::fetchOne(query) + .then([&gotValue](const Akonadi2::ApplicationDomain::Event &event) { + gotValue = true; + }).exec(); + result.waitForFinished(); + QVERIFY(!result.errorCode()); + QVERIFY(gotValue); + } + }; -- cgit v1.2.3