summaryrefslogtreecommitdiffstats
path: root/common/clientapi.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'common/clientapi.cpp')
-rw-r--r--common/clientapi.cpp62
1 files changed, 17 insertions, 45 deletions
diff --git a/common/clientapi.cpp b/common/clientapi.cpp
index 02f8ce6..b24dfa8 100644
--- a/common/clientapi.cpp
+++ b/common/clientapi.cpp
@@ -34,6 +34,7 @@
34#include "definitions.h" 34#include "definitions.h"
35#include "resourceconfig.h" 35#include "resourceconfig.h"
36#include "facadefactory.h" 36#include "facadefactory.h"
37#include "modelresult.h"
37#include "log.h" 38#include "log.h"
38 39
39#define ASYNCINTHREAD 40#define ASYNCINTHREAD
@@ -100,38 +101,8 @@ template <class DomainType>
100QSharedPointer<ResultEmitter<typename DomainType::Ptr> > Store::load(Query query) 101QSharedPointer<ResultEmitter<typename DomainType::Ptr> > Store::load(Query query)
101{ 102{
102 auto resultSet = QSharedPointer<ResultProvider<typename DomainType::Ptr> >::create(); 103 auto resultSet = QSharedPointer<ResultProvider<typename DomainType::Ptr> >::create();
103 104 qWarning() << "Main thread " << QThread::currentThreadId();
104 //Execute the search in a thread. 105 //FIXME remove
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(); 106 return resultSet->emitter();
136} 107}
137 108
@@ -139,28 +110,29 @@ template <class DomainType>
139QSharedPointer<QAbstractItemModel> Store::loadModel(Query query) 110QSharedPointer<QAbstractItemModel> Store::loadModel(Query query)
140{ 111{
141 auto model = QSharedPointer<ModelResult<DomainType, typename DomainType::Ptr> >::create(query, query.requestedProperties.toList()); 112 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); 113
143 //Keep the resultprovider alive for as long as the model lives 114 //* Client defines lifetime of model
144 model->setProperty("resultProvider", QVariant::fromValue(std::shared_ptr<void>(resultProvider))); 115 //* The model lifetime defines the duration of live-queries
116 //* The facade needs to life for the duration of any calls being made (assuming we get rid of any internal callbacks
117 //* The emitter needs to live or the duration of query (respectively, the model)
118 //* The result provider needs to live for as long as results are provided (until the last thread exits).
145 119
146 // Query all resources and aggregate results 120 // Query all resources and aggregate results
147 KAsync::iterate(getResources(query.resources, ApplicationDomain::getTypeName<DomainType>())) 121 KAsync::iterate(getResources(query.resources, ApplicationDomain::getTypeName<DomainType>()))
148 .template each<void, QByteArray>([query, resultProvider](const QByteArray &resource, KAsync::Future<void> &future) { 122 .template each<void, QByteArray>([query, model](const QByteArray &resource, KAsync::Future<void> &future) {
149 auto facade = FacadeFactory::instance().getFacade<DomainType>(resourceName(resource), resource); 123 auto facade = FacadeFactory::instance().getFacade<DomainType>(resourceName(resource), resource);
150 if (facade) { 124 if (facade) {
151 facade->load(query, *resultProvider).template then<void>([&future](){future.setFinished();}).exec(); 125 Trace() << "Trying to fetch from resource";
152 //Keep the facade alive for the lifetime of the resultSet. 126 auto result = facade->load(query);
153 //FIXME this would have to become a list 127 auto emitter = result.second;
154 resultProvider->setFacade(facade); 128 //TODO use aggregating emitter instead
129 model->setEmitter(emitter);
130 model->fetchMore(QModelIndex());
131 result.first.template then<void>([&future](){future.setFinished();}).exec();
155 } else { 132 } else {
156 //Ignore the error and carry on 133 //Ignore the error and carry on
157 future.setFinished(); 134 future.setFinished();
158 } 135 }
159 }).template then<void>([query, resultProvider]() {
160 resultProvider->initialResultSetComplete();
161 if (!query.liveQuery) {
162 resultProvider->complete();
163 }
164 }).exec(); 136 }).exec();
165 137
166 return model; 138 return model;