diff options
-rw-r--r-- | common/clientapi.cpp | 64 | ||||
-rw-r--r-- | common/clientapi.h | 9 | ||||
-rw-r--r-- | tests/clientapitest.cpp | 20 |
3 files changed, 93 insertions, 0 deletions
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<void> Store::synchronize(const Akonadi2::Query &query) | |||
212 | .template then<void>([](){}); | 212 | .template then<void>([](){}); |
213 | } | 213 | } |
214 | 214 | ||
215 | template <class DomainType> | ||
216 | KAsync::Job<DomainType> Store::fetchOne(const Akonadi2::Query &query) | ||
217 | { | ||
218 | return KAsync::start<DomainType>([query](KAsync::Future<DomainType> &future) { | ||
219 | //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) | ||
220 | fetch<DomainType>(query, 1) | ||
221 | .template then<void, QList<typename DomainType::Ptr> >([&future](const QList<typename DomainType::Ptr> &list){ | ||
222 | future.setValue(*list.first()); | ||
223 | future.setFinished(); | ||
224 | }, [&future](int errorCode, const QString &errorMessage) { | ||
225 | future.setError(errorCode, errorMessage); | ||
226 | future.setFinished(); | ||
227 | }).exec(); | ||
228 | }); | ||
229 | } | ||
230 | |||
231 | template <class DomainType> | ||
232 | KAsync::Job<QList<typename DomainType::Ptr> > Store::fetchAll(const Akonadi2::Query &query) | ||
233 | { | ||
234 | return fetch<DomainType>(query); | ||
235 | } | ||
236 | |||
237 | template <class DomainType> | ||
238 | KAsync::Job<QList<typename DomainType::Ptr> > Store::fetch(const Akonadi2::Query &query, int minimumAmount) | ||
239 | { | ||
240 | auto model = loadModel<DomainType>(query); | ||
241 | auto list = QSharedPointer<QList<typename DomainType::Ptr> >::create(); | ||
242 | auto context = QSharedPointer<QObject>::create(); | ||
243 | return KAsync::start<QList<typename DomainType::Ptr> >([model, list, context, minimumAmount](KAsync::Future<QList<typename DomainType::Ptr> > &future) { | ||
244 | if (model->rowCount() >= 1) { | ||
245 | for (int i = 0; i < model->rowCount(); i++) { | ||
246 | list->append(model->index(i, 0, QModelIndex()).data(Akonadi2::Store::DomainObjectRole).template value<typename DomainType::Ptr>()); | ||
247 | } | ||
248 | } else { | ||
249 | QObject::connect(model.data(), &QAbstractItemModel::rowsInserted, context.data(), [model, &future, list](const QModelIndex &index, int start, int end) { | ||
250 | for (int i = start; i <= end; i++) { | ||
251 | list->append(model->index(i, 0, QModelIndex()).data(Akonadi2::Store::DomainObjectRole).template value<typename DomainType::Ptr>()); | ||
252 | } | ||
253 | }); | ||
254 | QObject::connect(model.data(), &QAbstractItemModel::dataChanged, context.data(), [model, &future, list, minimumAmount](const QModelIndex &, const QModelIndex &, const QVector<int> &roles) { | ||
255 | if (roles.contains(ModelResult<DomainType, typename DomainType::Ptr>::ChildrenFetchedRole)) { | ||
256 | if (list->size() < minimumAmount) { | ||
257 | future.setError(1, "Not enough values."); | ||
258 | } else { | ||
259 | future.setValue(*list); | ||
260 | } | ||
261 | future.setFinished(); | ||
262 | } | ||
263 | }); | ||
264 | } | ||
265 | if (model->data(QModelIndex(), ModelResult<DomainType, typename DomainType::Ptr>::ChildrenFetchedRole).toBool()) { | ||
266 | if (list->size() < minimumAmount) { | ||
267 | future.setError(1, "Not enough values."); | ||
268 | } else { | ||
269 | future.setValue(*list); | ||
270 | } | ||
271 | future.setFinished(); | ||
272 | } | ||
273 | }); | ||
274 | } | ||
275 | |||
215 | #define REGISTER_TYPE(T) template KAsync::Job<void> Store::remove<T>(const T &domainObject); \ | 276 | #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); \ | 277 | template KAsync::Job<void> Store::create<T>(const T &domainObject); \ |
217 | template KAsync::Job<void> Store::modify<T>(const T &domainObject); \ | 278 | template KAsync::Job<void> Store::modify<T>(const T &domainObject); \ |
218 | template QSharedPointer<QAbstractItemModel> Store::loadModel<T>(Query query); \ | 279 | template QSharedPointer<QAbstractItemModel> Store::loadModel<T>(Query query); \ |
280 | template KAsync::Job<T> Store::fetchOne<T>(const Query &); \ | ||
281 | template KAsync::Job<QList<T::Ptr> > Store::fetchAll<T>(const Query &); \ | ||
282 | template KAsync::Job<QList<T::Ptr> > Store::fetch<T>(const Query &, int); \ | ||
219 | 283 | ||
220 | REGISTER_TYPE(ApplicationDomain::Event); | 284 | REGISTER_TYPE(ApplicationDomain::Event); |
221 | REGISTER_TYPE(ApplicationDomain::Mail); | 285 | 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: | |||
95 | * Removes a resource from disk. | 95 | * Removes a resource from disk. |
96 | */ | 96 | */ |
97 | static void removeFromDisk(const QByteArray &resourceIdentifier); | 97 | static void removeFromDisk(const QByteArray &resourceIdentifier); |
98 | |||
99 | template <class DomainType> | ||
100 | static KAsync::Job<DomainType> fetchOne(const Akonadi2::Query &query); | ||
101 | |||
102 | template <class DomainType> | ||
103 | static KAsync::Job<QList<typename DomainType::Ptr> > fetchAll(const Akonadi2::Query &query); | ||
104 | |||
105 | template <class DomainType> | ||
106 | static KAsync::Job<QList<typename DomainType::Ptr> > fetch(const Akonadi2::Query &query, int minimumAmount = 0); | ||
98 | }; | 107 | }; |
99 | 108 | ||
100 | 109 | ||
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: | |||
279 | QCOMPARE(childrenFetchedCount, 1); | 279 | QCOMPARE(childrenFetchedCount, 1); |
280 | } | 280 | } |
281 | 281 | ||
282 | void testImperativeLoad() | ||
283 | { | ||
284 | auto facade = DummyResourceFacade<Akonadi2::ApplicationDomain::Event>::registerFacade(); | ||
285 | facade->results << QSharedPointer<Akonadi2::ApplicationDomain::Event>::create("resource", "id", 0, QSharedPointer<Akonadi2::ApplicationDomain::MemoryBufferAdaptor>::create()); | ||
286 | ResourceConfig::addResource("dummyresource.instance1", "dummyresource"); | ||
287 | |||
288 | Akonadi2::Query query; | ||
289 | query.resources << "dummyresource.instance1"; | ||
290 | query.liveQuery = false; | ||
291 | |||
292 | bool gotValue = false; | ||
293 | auto result = Akonadi2::Store::fetchOne<Akonadi2::ApplicationDomain::Event>(query) | ||
294 | .then<void, Akonadi2::ApplicationDomain::Event>([&gotValue](const Akonadi2::ApplicationDomain::Event &event) { | ||
295 | gotValue = true; | ||
296 | }).exec(); | ||
297 | result.waitForFinished(); | ||
298 | QVERIFY(!result.errorCode()); | ||
299 | QVERIFY(gotValue); | ||
300 | } | ||
301 | |||
282 | 302 | ||
283 | }; | 303 | }; |
284 | 304 | ||