summaryrefslogtreecommitdiffstats
path: root/common/clientapi.cpp
diff options
context:
space:
mode:
authorChristian Mollekopf <chrigi_1@fastmail.fm>2015-11-30 18:49:04 +0100
committerChristian Mollekopf <chrigi_1@fastmail.fm>2015-11-30 18:49:04 +0100
commit412563b7ff18684f9786f4e40b1a4d538f2d5233 (patch)
tree3190a317306cfb71b0d5d9bc4c0f06b260a92ce6 /common/clientapi.cpp
parent790991aa1007d3271d80bc7e77f5b4f86c9bcef0 (diff)
parent6ad307dd846d07f1b55a1679a8d2eb47525af57d (diff)
downloadsink-412563b7ff18684f9786f4e40b1a4d538f2d5233.tar.gz
sink-412563b7ff18684f9786f4e40b1a4d538f2d5233.zip
Merge branch 'feature/modelresult' into develop
Diffstat (limited to 'common/clientapi.cpp')
-rw-r--r--common/clientapi.cpp117
1 files changed, 113 insertions, 4 deletions
diff --git a/common/clientapi.cpp b/common/clientapi.cpp
index f99ebb8..29b7e68 100644
--- a/common/clientapi.cpp
+++ b/common/clientapi.cpp
@@ -1,19 +1,47 @@
1/*
2 * Copyright (C) 2014 Christian Mollekopf <chrigi_1@fastmail.fm>
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) version 3, or any
8 * later version accepted by the membership of KDE e.V. (or its
9 * successor approved by the membership of KDE e.V.), which shall
10 * act as a proxy defined in Section 6 of version 3 of the license.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
19 */
1 20
2#include "clientapi.h" 21#include "clientapi.h"
22
23#include <QtConcurrent/QtConcurrentRun>
24#include <QTimer>
25#include <QEventLoop>
26#include <QAbstractItemModel>
27#include <functional>
28#include <memory>
29
3#include "resourceaccess.h" 30#include "resourceaccess.h"
4#include "commands.h" 31#include "commands.h"
5#include "resourcefacade.h" 32#include "resourcefacade.h"
6#include "log.h" 33#include "log.h"
7#include "definitions.h" 34#include "definitions.h"
8#include "resourceconfig.h" 35#include "resourceconfig.h"
9#include <QtConcurrent/QtConcurrentRun> 36#include "facadefactory.h"
10#include <QTimer> 37#include "modelresult.h"
38#include "log.h"
11 39
12#define ASYNCINTHREAD 40#define ASYNCINTHREAD
13 41
14namespace async 42namespace async
15{ 43{
16 void run(const std::function<void()> &runner) { 44 static void run(const std::function<void()> &runner) {
17 auto timer = new QTimer(); 45 auto timer = new QTimer();
18 timer->setSingleShot(true); 46 timer->setSingleShot(true);
19 QObject::connect(timer, &QTimer::timeout, [runner, timer]() { 47 QObject::connect(timer, &QTimer::timeout, [runner, timer]() {
@@ -69,6 +97,76 @@ QList<QByteArray> Store::getResources(const QList<QByteArray> &resourceFilter, c
69 return resources; 97 return resources;
70} 98}
71 99
100template <class DomainType>
101QSharedPointer<QAbstractItemModel> Store::loadModel(Query query)
102{
103 auto model = QSharedPointer<ModelResult<DomainType, typename DomainType::Ptr> >::create(query, query.requestedProperties.toList());
104
105 //* Client defines lifetime of model
106 //* The model lifetime defines the duration of live-queries
107 //* The facade needs to life for the duration of any calls being made (assuming we get rid of any internal callbacks
108 //* The emitter needs to live or the duration of query (respectively, the model)
109 //* The result provider needs to live for as long as results are provided (until the last thread exits).
110
111 // Query all resources and aggregate results
112 KAsync::iterate(getResources(query.resources, ApplicationDomain::getTypeName<DomainType>()))
113 .template each<void, QByteArray>([query, model](const QByteArray &resource, KAsync::Future<void> &future) {
114 auto facade = FacadeFactory::instance().getFacade<DomainType>(resourceName(resource), resource);
115 if (facade) {
116 Trace() << "Trying to fetch from resource";
117 auto result = facade->load(query);
118 auto emitter = result.second;
119 //TODO use aggregating emitter instead
120 model->setEmitter(emitter);
121 model->fetchMore(QModelIndex());
122 result.first.template then<void>([&future](){future.setFinished();}).exec();
123 } else {
124 //Ignore the error and carry on
125 future.setFinished();
126 }
127 }).exec();
128
129 return model;
130}
131
132template <class DomainType>
133static std::shared_ptr<StoreFacade<DomainType> > getFacade(const QByteArray &resourceInstanceIdentifier)
134{
135 if (auto facade = FacadeFactory::instance().getFacade<DomainType>(resourceName(resourceInstanceIdentifier), resourceInstanceIdentifier)) {
136 return facade;
137 }
138 return std::make_shared<NullFacade<DomainType> >();
139}
140
141template <class DomainType>
142KAsync::Job<void> Store::create(const DomainType &domainObject) {
143 //Potentially move to separate thread as well
144 auto facade = getFacade<DomainType>(domainObject.resourceInstanceIdentifier());
145 return facade->create(domainObject).template then<void>([facade](){}, [](int errorCode, const QString &error) {
146 Warning() << "Failed to create";
147 });
148}
149
150template <class DomainType>
151KAsync::Job<void> Store::modify(const DomainType &domainObject)
152{
153 //Potentially move to separate thread as well
154 auto facade = getFacade<DomainType>(domainObject.resourceInstanceIdentifier());
155 return facade->modify(domainObject).template then<void>([facade](){}, [](int errorCode, const QString &error) {
156 Warning() << "Failed to modify";
157 });
158}
159
160template <class DomainType>
161KAsync::Job<void> Store::remove(const DomainType &domainObject)
162{
163 //Potentially move to separate thread as well
164 auto facade = getFacade<DomainType>(domainObject.resourceInstanceIdentifier());
165 return facade->remove(domainObject).template then<void>([facade](){}, [](int errorCode, const QString &error) {
166 Warning() << "Failed to remove";
167 });
168}
169
72KAsync::Job<void> Store::shutdown(const QByteArray &identifier) 170KAsync::Job<void> Store::shutdown(const QByteArray &identifier)
73{ 171{
74 Trace() << "shutdown"; 172 Trace() << "shutdown";
@@ -95,7 +193,7 @@ KAsync::Job<void> Store::synchronize(const Akonadi2::Query &query)
95 .template each<void, QByteArray>([query](const QByteArray &resource, KAsync::Future<void> &future) { 193 .template each<void, QByteArray>([query](const QByteArray &resource, KAsync::Future<void> &future) {
96 auto resourceAccess = QSharedPointer<Akonadi2::ResourceAccess>::create(resource); 194 auto resourceAccess = QSharedPointer<Akonadi2::ResourceAccess>::create(resource);
97 resourceAccess->open(); 195 resourceAccess->open();
98 resourceAccess->synchronizeResource(true, false).then<void>([&future]() { 196 resourceAccess->synchronizeResource(query.syncOnDemand, query.processAll).then<void>([&future, resourceAccess]() {
99 future.setFinished(); 197 future.setFinished();
100 }).exec(); 198 }).exec();
101 }) 199 })
@@ -103,4 +201,15 @@ KAsync::Job<void> Store::synchronize(const Akonadi2::Query &query)
103 .template then<void>([](){}); 201 .template then<void>([](){});
104} 202}
105 203
204#define REGISTER_TYPE(T) template KAsync::Job<void> Store::remove<T>(const T &domainObject); \
205 template KAsync::Job<void> Store::create<T>(const T &domainObject); \
206 template KAsync::Job<void> Store::modify<T>(const T &domainObject); \
207 template QSharedPointer<QAbstractItemModel> Store::loadModel<T>(Query query); \
208
209REGISTER_TYPE(ApplicationDomain::Event);
210REGISTER_TYPE(ApplicationDomain::Mail);
211REGISTER_TYPE(ApplicationDomain::Folder);
212REGISTER_TYPE(ApplicationDomain::AkonadiResource);
213
106} // namespace Akonadi2 214} // namespace Akonadi2
215