summaryrefslogtreecommitdiffstats
path: root/common/clientapi.cpp
diff options
context:
space:
mode:
authorChristian Mollekopf <chrigi_1@fastmail.fm>2015-11-19 23:23:56 +0100
committerChristian Mollekopf <chrigi_1@fastmail.fm>2015-11-19 23:23:56 +0100
commit94a2cd6ec21bf0466a9a50d6e4a0a956ed47bc82 (patch)
tree8f05e8ed03691b006b1f2bf8f08bc21e582aad26 /common/clientapi.cpp
parentc4a6746e4420b580fe35cc89783de4dbc3205ac6 (diff)
downloadsink-94a2cd6ec21bf0466a9a50d6e4a0a956ed47bc82.tar.gz
sink-94a2cd6ec21bf0466a9a50d6e4a0a956ed47bc82.zip
Move implementations to the cpp file.
I finally figured out how to do that with cpp files. It requires instantiating the code with all expected classes, but that's not a big problem since we know all types. This will hopefully greatly reduce the compiletimes...
Diffstat (limited to 'common/clientapi.cpp')
-rw-r--r--common/clientapi.cpp151
1 files changed, 149 insertions, 2 deletions
diff --git a/common/clientapi.cpp b/common/clientapi.cpp
index 839e77b..02f8ce6 100644
--- a/common/clientapi.cpp
+++ b/common/clientapi.cpp
@@ -1,13 +1,40 @@
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 "log.h"
11 38
12#define ASYNCINTHREAD 39#define ASYNCINTHREAD
13 40
@@ -69,6 +96,114 @@ QList<QByteArray> Store::getResources(const QList<QByteArray> &resourceFilter, c
69 return resources; 96 return resources;
70} 97}
71 98
99template <class DomainType>
100QSharedPointer<ResultEmitter<typename DomainType::Ptr> > Store::load(Query query)
101{
102 auto resultSet = QSharedPointer<ResultProvider<typename DomainType::Ptr> >::create();
103
104 //Execute the search in a thread.
105 //We must guarantee that the emitter is returned before the first result is emitted.
106 //The result provider must be threadsafe.
107 async::run([query, resultSet](){
108 QEventLoop eventLoop;
109 resultSet->onDone([&eventLoop](){
110 eventLoop.quit();
111 });
112 // Query all resources and aggregate results
113 KAsync::iterate(getResources(query.resources, ApplicationDomain::getTypeName<DomainType>()))
114 .template each<void, QByteArray>([query, resultSet](const QByteArray &resource, KAsync::Future<void> &future) {
115 if (auto facade = FacadeFactory::instance().getFacade<DomainType>(resourceName(resource), resource)) {
116 facade->load(query, *resultSet).template then<void>([&future](){future.setFinished();}).exec();
117 //Keep the facade alive for the lifetime of the resultSet.
118 resultSet->setFacade(facade);
119 } else {
120 //Ignore the error and carry on
121 future.setFinished();
122 }
123 }).template then<void>([query, resultSet]() {
124 resultSet->initialResultSetComplete();
125 if (!query.liveQuery) {
126 resultSet->complete();
127 }
128 }).exec();
129
130 //Keep the thread alive until the result is ready
131 if (!resultSet->isDone()) {
132 eventLoop.exec();
133 }
134 });
135 return resultSet->emitter();
136}
137
138template <class DomainType>
139QSharedPointer<QAbstractItemModel> Store::loadModel(Query query)
140{
141 auto model = QSharedPointer<ModelResult<DomainType, typename DomainType::Ptr> >::create(query, query.requestedProperties.toList());
142 auto resultProvider = std::make_shared<ModelResultProvider<DomainType, typename DomainType::Ptr> >(model);
143 //Keep the resultprovider alive for as long as the model lives
144 model->setProperty("resultProvider", QVariant::fromValue(std::shared_ptr<void>(resultProvider)));
145
146 // Query all resources and aggregate results
147 KAsync::iterate(getResources(query.resources, ApplicationDomain::getTypeName<DomainType>()))
148 .template each<void, QByteArray>([query, resultProvider](const QByteArray &resource, KAsync::Future<void> &future) {
149 auto facade = FacadeFactory::instance().getFacade<DomainType>(resourceName(resource), resource);
150 if (facade) {
151 facade->load(query, *resultProvider).template then<void>([&future](){future.setFinished();}).exec();
152 //Keep the facade alive for the lifetime of the resultSet.
153 //FIXME this would have to become a list
154 resultProvider->setFacade(facade);
155 } else {
156 //Ignore the error and carry on
157 future.setFinished();
158 }
159 }).template then<void>([query, resultProvider]() {
160 resultProvider->initialResultSetComplete();
161 if (!query.liveQuery) {
162 resultProvider->complete();
163 }
164 }).exec();
165
166 return model;
167}
168
169template <class DomainType>
170static std::shared_ptr<StoreFacade<DomainType> > getFacade(const QByteArray &resourceInstanceIdentifier)
171{
172 if (auto facade = FacadeFactory::instance().getFacade<DomainType>(resourceName(resourceInstanceIdentifier), resourceInstanceIdentifier)) {
173 return facade;
174 }
175 return std::make_shared<NullFacade<DomainType> >();
176}
177
178template <class DomainType>
179KAsync::Job<void> Store::create(const DomainType &domainObject) {
180 //Potentially move to separate thread as well
181 auto facade = getFacade<DomainType>(domainObject.resourceInstanceIdentifier());
182 return facade->create(domainObject).template then<void>([facade](){}, [](int errorCode, const QString &error) {
183 Warning() << "Failed to create";
184 });
185}
186
187template <class DomainType>
188KAsync::Job<void> Store::modify(const DomainType &domainObject)
189{
190 //Potentially move to separate thread as well
191 auto facade = getFacade<DomainType>(domainObject.resourceInstanceIdentifier());
192 return facade->modify(domainObject).template then<void>([facade](){}, [](int errorCode, const QString &error) {
193 Warning() << "Failed to modify";
194 });
195}
196
197template <class DomainType>
198KAsync::Job<void> Store::remove(const DomainType &domainObject)
199{
200 //Potentially move to separate thread as well
201 auto facade = getFacade<DomainType>(domainObject.resourceInstanceIdentifier());
202 return facade->remove(domainObject).template then<void>([facade](){}, [](int errorCode, const QString &error) {
203 Warning() << "Failed to remove";
204 });
205}
206
72KAsync::Job<void> Store::shutdown(const QByteArray &identifier) 207KAsync::Job<void> Store::shutdown(const QByteArray &identifier)
73{ 208{
74 Trace() << "shutdown"; 209 Trace() << "shutdown";
@@ -103,4 +238,16 @@ KAsync::Job<void> Store::synchronize(const Akonadi2::Query &query)
103 .template then<void>([](){}); 238 .template then<void>([](){});
104} 239}
105 240
241#define REGISTER_TYPE(T) template KAsync::Job<void> Store::remove<T>(const T &domainObject); \
242 template KAsync::Job<void> Store::create<T>(const T &domainObject); \
243 template KAsync::Job<void> Store::modify<T>(const T &domainObject); \
244 template QSharedPointer<ResultEmitter<typename T::Ptr> > Store::load<T>(Query query); \
245 template QSharedPointer<QAbstractItemModel> Store::loadModel<T>(Query query); \
246
247REGISTER_TYPE(ApplicationDomain::Event);
248REGISTER_TYPE(ApplicationDomain::Mail);
249REGISTER_TYPE(ApplicationDomain::Folder);
250REGISTER_TYPE(ApplicationDomain::AkonadiResource);
251
106} // namespace Akonadi2 252} // namespace Akonadi2
253