diff options
-rw-r--r-- | common/clientapi.h | 3 | ||||
-rw-r--r-- | common/modelresult.cpp | 30 | ||||
-rw-r--r-- | common/modelresult.h | 8 | ||||
-rw-r--r-- | common/queryrunner.cpp | 1 | ||||
-rw-r--r-- | common/resourcefacade.cpp | 2 | ||||
-rw-r--r-- | common/resultprovider.h | 30 |
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 | |||
122 | template<class T, class Ptr> | 125 | template<class T, class Ptr> |
123 | bool ModelResult<T, Ptr>::canFetchMore(const QModelIndex &parent) const | 126 | bool 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 | ||
129 | template<class T, class Ptr> | 132 | template<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> | |||
185 | void ModelResult<T, Ptr>::fetchEntities(const QModelIndex &parent) | 189 | void 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 | ||
222 | template<class T, class Ptr> | 226 | template<class T, class Ptr> |
227 | bool ModelResult<T, Ptr>::childrenFetched(const QModelIndex &index) const | ||
228 | { | ||
229 | return mEntityChildrenFetchComplete.contains(getIdentifier(index)); | ||
230 | } | ||
231 | |||
232 | template<class T, class Ptr> | ||
223 | void ModelResult<T, Ptr>::modify(const Ptr &value) | 233 | void 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 | { |
34 | public: | 34 | public: |
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 | |||
59 | private: | 62 | private: |
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; |