summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--common/clientapi.h3
-rw-r--r--common/modelresult.cpp30
-rw-r--r--common/modelresult.h8
-rw-r--r--common/queryrunner.cpp1
-rw-r--r--common/resourcefacade.cpp2
-rw-r--r--common/resultprovider.h30
6 files changed, 51 insertions, 23 deletions
diff --git a/common/clientapi.h b/common/clientapi.h
index 04f1305..8f87562 100644
--- a/common/clientapi.h
+++ b/common/clientapi.h
@@ -44,7 +44,8 @@ public:
44 static QByteArray resourceName(const QByteArray &instanceIdentifier); 44 static QByteArray resourceName(const QByteArray &instanceIdentifier);
45 45
46 enum Roles { 46 enum Roles {
47 DomainObjectRole = Qt::UserRole + 1 //Must be the same as in ModelResult 47 DomainObjectRole = Qt::UserRole + 1, //Must be the same as in ModelResult
48 ChildrenFetchedRole
48 }; 49 };
49 50
50 /** 51 /**
diff --git a/common/modelresult.cpp b/common/modelresult.cpp
index 582f8ff..4def20f 100644
--- a/common/modelresult.cpp
+++ b/common/modelresult.cpp
@@ -74,6 +74,9 @@ QVariant ModelResult<T, Ptr>::data(const QModelIndex &index, int role) const
74 Q_ASSERT(mEntities.contains(index.internalId())); 74 Q_ASSERT(mEntities.contains(index.internalId()));
75 return QVariant::fromValue(mEntities.value(index.internalId())); 75 return QVariant::fromValue(mEntities.value(index.internalId()));
76 } 76 }
77 if (role == ChildrenFetchedRole) {
78 return childrenFetched(index);
79 }
77 if (role == Qt::DisplayRole) { 80 if (role == Qt::DisplayRole) {
78 if (index.column() < mPropertyColumns.size()) { 81 if (index.column() < mPropertyColumns.size()) {
79 Q_ASSERT(mEntities.contains(index.internalId())); 82 Q_ASSERT(mEntities.contains(index.internalId()));
@@ -122,8 +125,8 @@ bool ModelResult<T, Ptr>::hasChildren(const QModelIndex &parent) const
122template<class T, class Ptr> 125template<class T, class Ptr>
123bool ModelResult<T, Ptr>::canFetchMore(const QModelIndex &parent) const 126bool ModelResult<T, Ptr>::canFetchMore(const QModelIndex &parent) const
124{ 127{
125 qDebug() << "Can fetch more: " << parent << mEntityChildrenFetched.value(parent.internalId()); 128 qDebug() << "Can fetch more: " << parent << mEntityChildrenFetched.contains(parent.internalId());
126 return !mEntityChildrenFetched.value(parent.internalId(), false); 129 return !mEntityChildrenFetched.contains(parent.internalId());
127} 130}
128 131
129template<class T, class Ptr> 132template<class T, class Ptr>
@@ -139,7 +142,8 @@ void ModelResult<T, Ptr>::add(const Ptr &value)
139 const auto childId = qHash(value->identifier()); 142 const auto childId = qHash(value->identifier());
140 const auto id = parentId(value); 143 const auto id = parentId(value);
141 //Ignore updates we get before the initial fetch is done 144 //Ignore updates we get before the initial fetch is done
142 if (!mEntityChildrenFetched[id]) { 145 if (!mEntityChildrenFetched.contains(id)) {
146 qDebug() << "Children not yet fetched";
143 return; 147 return;
144 } 148 }
145 auto parent = createIndexFromId(id); 149 auto parent = createIndexFromId(id);
@@ -185,7 +189,7 @@ template<class T, class Ptr>
185void ModelResult<T, Ptr>::fetchEntities(const QModelIndex &parent) 189void ModelResult<T, Ptr>::fetchEntities(const QModelIndex &parent)
186{ 190{
187 const auto id = getIdentifier(parent); 191 const auto id = getIdentifier(parent);
188 mEntityChildrenFetched[id] = true; 192 mEntityChildrenFetched.insert(id);
189 Trace() << "Loading child entities"; 193 Trace() << "Loading child entities";
190 loadEntities(parent.data(DomainObjectRole).template value<Ptr>()); 194 loadEntities(parent.data(DomainObjectRole).template value<Ptr>());
191} 195}
@@ -210,22 +214,28 @@ void ModelResult<T, Ptr>::setEmitter(const typename Akonadi2::ResultEmitter<Ptr>
210 emitter->onRemoved([this](const Ptr &value) { 214 emitter->onRemoved([this](const Ptr &value) {
211 this->remove(value); 215 this->remove(value);
212 }); 216 });
213 emitter->onInitialResultSetComplete([this]() { 217 emitter->onInitialResultSetComplete([this](const Ptr &parent) {
214 }); 218 qint64 parentId = parent ? qHash(parent->identifier()) : 0;
215 emitter->onComplete([this]() { 219 const auto parentIndex = createIndexFromId(parentId);
216 }); 220 mEntityChildrenFetchComplete.insert(parentId);
217 emitter->onClear([this]() { 221 emit dataChanged(parentIndex, parentIndex, QVector<int>() << ChildrenFetchedRole);
218 }); 222 });
219 mEmitter = emitter; 223 mEmitter = emitter;
220} 224}
221 225
222template<class T, class Ptr> 226template<class T, class Ptr>
227bool ModelResult<T, Ptr>::childrenFetched(const QModelIndex &index) const
228{
229 return mEntityChildrenFetchComplete.contains(getIdentifier(index));
230}
231
232template<class T, class Ptr>
223void ModelResult<T, Ptr>::modify(const Ptr &value) 233void ModelResult<T, Ptr>::modify(const Ptr &value)
224{ 234{
225 auto childId = qHash(value->identifier()); 235 auto childId = qHash(value->identifier());
226 auto id = parentId(value); 236 auto id = parentId(value);
227 //Ignore updates we get before the initial fetch is done 237 //Ignore updates we get before the initial fetch is done
228 if (!mEntityChildrenFetched[id]) { 238 if (!mEntityChildrenFetched.contains(id)) {
229 return; 239 return;
230 } 240 }
231 auto parent = createIndexFromId(id); 241 auto parent = createIndexFromId(id);
diff --git a/common/modelresult.h b/common/modelresult.h
index 3ccf629..700064b 100644
--- a/common/modelresult.h
+++ b/common/modelresult.h
@@ -33,7 +33,8 @@ class ModelResult : public QAbstractItemModel
33{ 33{
34public: 34public:
35 enum Roles { 35 enum Roles {
36 DomainObjectRole = Qt::UserRole + 1 36 DomainObjectRole = Qt::UserRole + 1,
37 ChildrenFetchedRole
37 }; 38 };
38 39
39 ModelResult(const Akonadi2::Query &query, const QList<QByteArray> &propertyColumns); 40 ModelResult(const Akonadi2::Query &query, const QList<QByteArray> &propertyColumns);
@@ -56,6 +57,8 @@ public:
56 57
57 void setFetcher(const std::function<void(const Ptr &parent)> &fetcher); 58 void setFetcher(const std::function<void(const Ptr &parent)> &fetcher);
58 59
60 bool childrenFetched(const QModelIndex &) const;
61
59private: 62private:
60 qint64 parentId(const Ptr &value); 63 qint64 parentId(const Ptr &value);
61 QModelIndex createIndexFromId(const qint64 &id) const; 64 QModelIndex createIndexFromId(const qint64 &id) const;
@@ -65,7 +68,8 @@ private:
65 QMap<qint64 /* entity id */, Ptr> mEntities; 68 QMap<qint64 /* entity id */, Ptr> mEntities;
66 QMap<qint64 /* parent entity id */, QList<qint64> /* child entity id*/> mTree; 69 QMap<qint64 /* parent entity id */, QList<qint64> /* child entity id*/> mTree;
67 QMap<qint64 /* child entity id */, qint64 /* parent entity id*/> mParents; 70 QMap<qint64 /* child entity id */, qint64 /* parent entity id*/> mParents;
68 QMap<qint64 /* entity id */, bool> mEntityChildrenFetched; 71 QSet<qint64 /* entity id */> mEntityChildrenFetched;
72 QSet<qint64 /* entity id */> mEntityChildrenFetchComplete;
69 QList<QByteArray> mPropertyColumns; 73 QList<QByteArray> mPropertyColumns;
70 Akonadi2::Query mQuery; 74 Akonadi2::Query mQuery;
71 std::function<void(const Ptr &)> loadEntities; 75 std::function<void(const Ptr &)> loadEntities;
diff --git a/common/queryrunner.cpp b/common/queryrunner.cpp
index bb1127c..e365cfc 100644
--- a/common/queryrunner.cpp
+++ b/common/queryrunner.cpp
@@ -303,6 +303,7 @@ qint64 QueryRunner<DomainType>::executeInitialQuery(const Akonadi2::Query &query
303 return loadInitialResultSet(modifiedQuery, transaction, remainingFilters); 303 return loadInitialResultSet(modifiedQuery, transaction, remainingFilters);
304 }, resultProvider, true); 304 }, resultProvider, true);
305 Trace() << "Initial query took: " << time.elapsed() << " ms"; 305 Trace() << "Initial query took: " << time.elapsed() << " ms";
306 resultProvider.initialResultSetComplete(parent);
306 return revision; 307 return revision;
307} 308}
308 309
diff --git a/common/resourcefacade.cpp b/common/resourcefacade.cpp
index 3d207e4..6510c90 100644
--- a/common/resourcefacade.cpp
+++ b/common/resourcefacade.cpp
@@ -74,7 +74,7 @@ QPair<KAsync::Job<void>, typename Akonadi2::ResultEmitter<Akonadi2::ApplicationD
74 } 74 }
75 } 75 }
76 //TODO initialResultSetComplete should be implicit 76 //TODO initialResultSetComplete should be implicit
77 resultProvider->initialResultSetComplete(); 77 resultProvider->initialResultSetComplete(Akonadi2::ApplicationDomain::AkonadiResource::Ptr());
78 resultProvider->complete(); 78 resultProvider->complete();
79 }); 79 });
80 return qMakePair(job, emitter); 80 return qMakePair(job, emitter);
diff --git a/common/resultprovider.h b/common/resultprovider.h
index 6d7867a..d50f3f6 100644
--- a/common/resultprovider.h
+++ b/common/resultprovider.h
@@ -50,7 +50,7 @@ public:
50 virtual void add(const T &value) = 0; 50 virtual void add(const T &value) = 0;
51 virtual void modify(const T &value) = 0; 51 virtual void modify(const T &value) = 0;
52 virtual void remove(const T &value) = 0; 52 virtual void remove(const T &value) = 0;
53 virtual void initialResultSetComplete() = 0; 53 virtual void initialResultSetComplete(const T &parent) = 0;
54 virtual void complete() = 0; 54 virtual void complete() = 0;
55 virtual void clear() = 0; 55 virtual void clear() = 0;
56 virtual void setFetcher(const std::function<void(const T &parent)> &fetcher) = 0; 56 virtual void setFetcher(const std::function<void(const T &parent)> &fetcher) = 0;
@@ -144,9 +144,15 @@ public:
144 }); 144 });
145 } 145 }
146 146
147 void initialResultSetComplete() 147 void initialResultSetComplete(const T &parent)
148 { 148 {
149 callInMainThreadOnEmitter(&ResultEmitter<T>::initialResultSetComplete); 149 //Because I don't know how to use bind
150 auto weakEmitter = mResultEmitter;
151 callInMainThreadOnEmitter([weakEmitter, parent](){
152 if (auto strongRef = weakEmitter.toStrongRef()) {
153 strongRef->initialResultSetComplete(parent);
154 }
155 });
150 } 156 }
151 157
152 //Called from worker thread 158 //Called from worker thread
@@ -244,7 +250,7 @@ public:
244 removeHandler = handler; 250 removeHandler = handler;
245 } 251 }
246 252
247 void onInitialResultSetComplete(const std::function<void(void)> &handler) 253 void onInitialResultSetComplete(const std::function<void(const DomainType&)> &handler)
248 { 254 {
249 initialResultSetCompleteHandler = handler; 255 initialResultSetCompleteHandler = handler;
250 } 256 }
@@ -274,19 +280,25 @@ public:
274 removeHandler(value); 280 removeHandler(value);
275 } 281 }
276 282
277 void initialResultSetComplete() 283 void initialResultSetComplete(const DomainType &parent)
278 { 284 {
279 initialResultSetCompleteHandler(); 285 if (initialResultSetCompleteHandler) {
286 initialResultSetCompleteHandler(parent);
287 }
280 } 288 }
281 289
282 void complete() 290 void complete()
283 { 291 {
284 completeHandler(); 292 if (completeHandler) {
293 completeHandler();
294 }
285 } 295 }
286 296
287 void clear() 297 void clear()
288 { 298 {
289 clearHandler(); 299 if (clearHandler) {
300 clearHandler();
301 }
290 } 302 }
291 303
292 void setFetcher(const std::function<void(const DomainType &parent)> &fetcher) 304 void setFetcher(const std::function<void(const DomainType &parent)> &fetcher)
@@ -302,7 +314,7 @@ private:
302 std::function<void(const DomainType&)> addHandler; 314 std::function<void(const DomainType&)> addHandler;
303 std::function<void(const DomainType&)> modifyHandler; 315 std::function<void(const DomainType&)> modifyHandler;
304 std::function<void(const DomainType&)> removeHandler; 316 std::function<void(const DomainType&)> removeHandler;
305 std::function<void(void)> initialResultSetCompleteHandler; 317 std::function<void(const DomainType&)> initialResultSetCompleteHandler;
306 std::function<void(void)> completeHandler; 318 std::function<void(void)> completeHandler;
307 std::function<void(void)> clearHandler; 319 std::function<void(void)> clearHandler;
308 ThreadBoundary mThreadBoundary; 320 ThreadBoundary mThreadBoundary;