diff options
-rw-r--r-- | common/domain/applicationdomaintype.h | 9 | ||||
-rw-r--r-- | common/entitystorage.h | 3 | ||||
-rw-r--r-- | common/resultprovider.h | 49 | ||||
-rw-r--r-- | common/synclistresult.h | 18 | ||||
-rw-r--r-- | tests/genericfacadetest.cpp | 79 |
5 files changed, 154 insertions, 4 deletions
diff --git a/common/domain/applicationdomaintype.h b/common/domain/applicationdomaintype.h index e0a6de0..b583a6e 100644 --- a/common/domain/applicationdomaintype.h +++ b/common/domain/applicationdomaintype.h | |||
@@ -97,6 +97,15 @@ private: | |||
97 | qint64 mRevision; | 97 | qint64 mRevision; |
98 | }; | 98 | }; |
99 | 99 | ||
100 | /* | ||
101 | * Should this be specific to the synclistresultset, in other cases we may want to take revision and resource into account. | ||
102 | */ | ||
103 | inline bool operator==(const ApplicationDomainType& lhs, const ApplicationDomainType& rhs) | ||
104 | { | ||
105 | return lhs.identifier() == rhs.identifier() | ||
106 | && lhs.resourceInstanceIdentifier() == rhs.resourceInstanceIdentifier(); | ||
107 | } | ||
108 | |||
100 | struct Event : public ApplicationDomainType { | 109 | struct Event : public ApplicationDomainType { |
101 | typedef QSharedPointer<Event> Ptr; | 110 | typedef QSharedPointer<Event> Ptr; |
102 | using ApplicationDomainType::ApplicationDomainType; | 111 | using ApplicationDomainType::ApplicationDomainType; |
diff --git a/common/entitystorage.h b/common/entitystorage.h index 78dbcda..6b09cad 100644 --- a/common/entitystorage.h +++ b/common/entitystorage.h | |||
@@ -118,10 +118,11 @@ public: | |||
118 | break; | 118 | break; |
119 | case Akonadi2::Operation_Modification: | 119 | case Akonadi2::Operation_Modification: |
120 | Trace() << "Got modification"; | 120 | Trace() << "Got modification"; |
121 | resultProvider->add(copy(*value).template staticCast<DomainType>()); | 121 | resultProvider->modify(copy(*value).template staticCast<DomainType>()); |
122 | break; | 122 | break; |
123 | case Akonadi2::Operation_Removal: | 123 | case Akonadi2::Operation_Removal: |
124 | Trace() << "Got removal"; | 124 | Trace() << "Got removal"; |
125 | resultProvider->remove(copy(*value).template staticCast<DomainType>()); | ||
125 | break; | 126 | break; |
126 | } | 127 | } |
127 | return true; | 128 | return true; |
diff --git a/common/resultprovider.h b/common/resultprovider.h index 841fd01..bc03152 100644 --- a/common/resultprovider.h +++ b/common/resultprovider.h | |||
@@ -81,6 +81,28 @@ public: | |||
81 | }); | 81 | }); |
82 | } | 82 | } |
83 | 83 | ||
84 | void modify(const T &value) | ||
85 | { | ||
86 | //Because I don't know how to use bind | ||
87 | auto weakEmitter = mResultEmitter; | ||
88 | callInMainThreadOnEmitter([weakEmitter, value](){ | ||
89 | if (auto strongRef = weakEmitter.toStrongRef()) { | ||
90 | strongRef->modifyHandler(value); | ||
91 | } | ||
92 | }); | ||
93 | } | ||
94 | |||
95 | void remove(const T &value) | ||
96 | { | ||
97 | //Because I don't know how to use bind | ||
98 | auto weakEmitter = mResultEmitter; | ||
99 | callInMainThreadOnEmitter([weakEmitter, value](){ | ||
100 | if (auto strongRef = weakEmitter.toStrongRef()) { | ||
101 | strongRef->removeHandler(value); | ||
102 | } | ||
103 | }); | ||
104 | } | ||
105 | |||
84 | void initialResultSetComplete() | 106 | void initialResultSetComplete() |
85 | { | 107 | { |
86 | callInMainThreadOnEmitter(&ResultEmitter<T>::initialResultSetComplete); | 108 | callInMainThreadOnEmitter(&ResultEmitter<T>::initialResultSetComplete); |
@@ -176,15 +198,27 @@ public: | |||
176 | { | 198 | { |
177 | addHandler = handler; | 199 | addHandler = handler; |
178 | } | 200 | } |
179 | // void onRemoved(const std::function<void(const T&)> &handler); | 201 | |
202 | void onModified(const std::function<void(const DomainType&)> &handler) | ||
203 | { | ||
204 | modifyHandler = handler; | ||
205 | } | ||
206 | |||
207 | void onRemoved(const std::function<void(const DomainType&)> &handler) | ||
208 | { | ||
209 | removeHandler = handler; | ||
210 | } | ||
211 | |||
180 | void onInitialResultSetComplete(const std::function<void(void)> &handler) | 212 | void onInitialResultSetComplete(const std::function<void(void)> &handler) |
181 | { | 213 | { |
182 | initialResultSetCompleteHandler = handler; | 214 | initialResultSetCompleteHandler = handler; |
183 | } | 215 | } |
216 | |||
184 | void onComplete(const std::function<void(void)> &handler) | 217 | void onComplete(const std::function<void(void)> &handler) |
185 | { | 218 | { |
186 | completeHandler = handler; | 219 | completeHandler = handler; |
187 | } | 220 | } |
221 | |||
188 | void onClear(const std::function<void(void)> &handler) | 222 | void onClear(const std::function<void(void)> &handler) |
189 | { | 223 | { |
190 | clearHandler = handler; | 224 | clearHandler = handler; |
@@ -195,6 +229,16 @@ public: | |||
195 | addHandler(value); | 229 | addHandler(value); |
196 | } | 230 | } |
197 | 231 | ||
232 | void modify(const DomainType &value) | ||
233 | { | ||
234 | modifyHandler(value); | ||
235 | } | ||
236 | |||
237 | void remove(const DomainType &value) | ||
238 | { | ||
239 | removeHandler(value); | ||
240 | } | ||
241 | |||
198 | void initialResultSetComplete() | 242 | void initialResultSetComplete() |
199 | { | 243 | { |
200 | initialResultSetCompleteHandler(); | 244 | initialResultSetCompleteHandler(); |
@@ -214,7 +258,8 @@ private: | |||
214 | friend class ResultProvider<DomainType>; | 258 | friend class ResultProvider<DomainType>; |
215 | 259 | ||
216 | std::function<void(const DomainType&)> addHandler; | 260 | std::function<void(const DomainType&)> addHandler; |
217 | // std::function<void(const T&)> removeHandler; | 261 | std::function<void(const DomainType&)> modifyHandler; |
262 | std::function<void(const DomainType&)> removeHandler; | ||
218 | std::function<void(void)> initialResultSetCompleteHandler; | 263 | std::function<void(void)> initialResultSetCompleteHandler; |
219 | std::function<void(void)> completeHandler; | 264 | std::function<void(void)> completeHandler; |
220 | std::function<void(void)> clearHandler; | 265 | std::function<void(void)> clearHandler; |
diff --git a/common/synclistresult.h b/common/synclistresult.h index 865d3e0..3ae2bed 100644 --- a/common/synclistresult.h +++ b/common/synclistresult.h | |||
@@ -4,6 +4,7 @@ | |||
4 | #include <functional> | 4 | #include <functional> |
5 | #include <QSharedPointer> | 5 | #include <QSharedPointer> |
6 | #include <QEventLoop> | 6 | #include <QEventLoop> |
7 | #include <QDebug> | ||
7 | #include "resultprovider.h" | 8 | #include "resultprovider.h" |
8 | 9 | ||
9 | namespace async { | 10 | namespace async { |
@@ -25,6 +26,23 @@ public: | |||
25 | emitter->onAdded([this](const T &value) { | 26 | emitter->onAdded([this](const T &value) { |
26 | this->append(value); | 27 | this->append(value); |
27 | }); | 28 | }); |
29 | emitter->onModified([this](const T &value) { | ||
30 | for (auto it = this->begin(); it != this->end(); it++) { | ||
31 | if (**it == *value) { | ||
32 | it = this->erase(it); | ||
33 | this->insert(it, value); | ||
34 | break; | ||
35 | } | ||
36 | } | ||
37 | }); | ||
38 | emitter->onRemoved([this](const T &value) { | ||
39 | for (auto it = this->begin(); it != this->end(); it++) { | ||
40 | if (**it == *value) { | ||
41 | this->erase(it); | ||
42 | break; | ||
43 | } | ||
44 | } | ||
45 | }); | ||
28 | emitter->onInitialResultSetComplete([this]() { | 46 | emitter->onInitialResultSetComplete([this]() { |
29 | if (eventLoopAborter) { | 47 | if (eventLoopAborter) { |
30 | eventLoopAborter(); | 48 | eventLoopAborter(); |
diff --git a/tests/genericfacadetest.cpp b/tests/genericfacadetest.cpp index f21de70..e9c1a94 100644 --- a/tests/genericfacadetest.cpp +++ b/tests/genericfacadetest.cpp | |||
@@ -30,10 +30,18 @@ public: | |||
30 | for (const auto &res : mResults) { | 30 | for (const auto &res : mResults) { |
31 | resultProvider->add(res); | 31 | resultProvider->add(res); |
32 | } | 32 | } |
33 | for (const auto &res : mModifications) { | ||
34 | resultProvider->modify(res); | ||
35 | } | ||
36 | for (const auto &res : mRemovals) { | ||
37 | resultProvider->remove(res); | ||
38 | } | ||
33 | return mLatestRevision; | 39 | return mLatestRevision; |
34 | } | 40 | } |
35 | 41 | ||
36 | QList<Akonadi2::ApplicationDomain::Event::Ptr> mResults; | 42 | QList<Akonadi2::ApplicationDomain::Event::Ptr> mResults; |
43 | QList<Akonadi2::ApplicationDomain::Event::Ptr> mModifications; | ||
44 | QList<Akonadi2::ApplicationDomain::Event::Ptr> mRemovals; | ||
37 | qint64 mLatestRevision; | 45 | qint64 mLatestRevision; |
38 | }; | 46 | }; |
39 | 47 | ||
@@ -126,9 +134,78 @@ private Q_SLOTS: | |||
126 | resultSet->initialResultSetComplete(); | 134 | resultSet->initialResultSetComplete(); |
127 | result.exec(); | 135 | result.exec(); |
128 | 136 | ||
129 | // QTRY_COMPARE(result.size(), 2); | ||
130 | QCOMPARE(result.size(), 2); | 137 | QCOMPARE(result.size(), 2); |
131 | } | 138 | } |
139 | |||
140 | void testLiveQueryModify() | ||
141 | { | ||
142 | Akonadi2::Query query; | ||
143 | query.liveQuery = true; | ||
144 | |||
145 | auto resultSet = QSharedPointer<Akonadi2::ResultProvider<Akonadi2::ApplicationDomain::Event::Ptr> >::create(); | ||
146 | auto storage = QSharedPointer<TestEntityStorage>::create("identifier", QSharedPointer<TestEventAdaptorFactory>::create(), "bufferType"); | ||
147 | auto resourceAccess = QSharedPointer<TestResourceAccess>::create(); | ||
148 | auto entity = QSharedPointer<Akonadi2::ApplicationDomain::Event>::create("resource", "id2", 0, QSharedPointer<Akonadi2::ApplicationDomain::MemoryBufferAdaptor>::create()); | ||
149 | entity->setProperty("test", "test1"); | ||
150 | storage->mResults << entity; | ||
151 | TestResourceFacade facade("identifier", storage, resourceAccess); | ||
152 | |||
153 | async::SyncListResult<Akonadi2::ApplicationDomain::Event::Ptr> result(resultSet->emitter()); | ||
154 | |||
155 | facade.load(query, resultSet).exec().waitForFinished(); | ||
156 | resultSet->initialResultSetComplete(); | ||
157 | |||
158 | result.exec(); | ||
159 | QCOMPARE(result.size(), 1); | ||
160 | |||
161 | //Modify the entity again | ||
162 | storage->mResults.clear(); | ||
163 | entity = QSharedPointer<Akonadi2::ApplicationDomain::Event>::create("resource", "id2", 0, QSharedPointer<Akonadi2::ApplicationDomain::MemoryBufferAdaptor>::create()); | ||
164 | entity->setProperty("test", "test2"); | ||
165 | storage->mModifications << entity; | ||
166 | storage->mLatestRevision = 2; | ||
167 | resourceAccess->emit revisionChanged(2); | ||
168 | |||
169 | //Hack to get event loop in synclistresult to abort again | ||
170 | resultSet->initialResultSetComplete(); | ||
171 | result.exec(); | ||
172 | |||
173 | QCOMPARE(result.size(), 1); | ||
174 | QCOMPARE(result.first()->getProperty("test").toByteArray(), QByteArray("test2")); | ||
175 | } | ||
176 | |||
177 | void testLiveQueryRemove() | ||
178 | { | ||
179 | Akonadi2::Query query; | ||
180 | query.liveQuery = true; | ||
181 | |||
182 | auto resultSet = QSharedPointer<Akonadi2::ResultProvider<Akonadi2::ApplicationDomain::Event::Ptr> >::create(); | ||
183 | auto storage = QSharedPointer<TestEntityStorage>::create("identifier", QSharedPointer<TestEventAdaptorFactory>::create(), "bufferType"); | ||
184 | auto resourceAccess = QSharedPointer<TestResourceAccess>::create(); | ||
185 | auto entity = QSharedPointer<Akonadi2::ApplicationDomain::Event>::create("resource", "id2", 0, QSharedPointer<Akonadi2::ApplicationDomain::BufferAdaptor>()); | ||
186 | storage->mResults << entity; | ||
187 | TestResourceFacade facade("identifier", storage, resourceAccess); | ||
188 | |||
189 | async::SyncListResult<Akonadi2::ApplicationDomain::Event::Ptr> result(resultSet->emitter()); | ||
190 | |||
191 | facade.load(query, resultSet).exec().waitForFinished(); | ||
192 | resultSet->initialResultSetComplete(); | ||
193 | |||
194 | result.exec(); | ||
195 | QCOMPARE(result.size(), 1); | ||
196 | |||
197 | //Remove the entity again | ||
198 | storage->mResults.clear(); | ||
199 | storage->mRemovals << entity; | ||
200 | storage->mLatestRevision = 2; | ||
201 | resourceAccess->emit revisionChanged(2); | ||
202 | |||
203 | //Hack to get event loop in synclistresult to abort again | ||
204 | resultSet->initialResultSetComplete(); | ||
205 | result.exec(); | ||
206 | |||
207 | QCOMPARE(result.size(), 0); | ||
208 | } | ||
132 | }; | 209 | }; |
133 | 210 | ||
134 | QTEST_MAIN(GenericFacadeTest) | 211 | QTEST_MAIN(GenericFacadeTest) |