diff options
-rw-r--r-- | client/clientapi.h | 45 | ||||
-rw-r--r-- | client/test/clientapitest.cpp | 12 |
2 files changed, 48 insertions, 9 deletions
diff --git a/client/clientapi.h b/client/clientapi.h index 592fa48..662f96c 100644 --- a/client/clientapi.h +++ b/client/clientapi.h | |||
@@ -6,6 +6,7 @@ | |||
6 | #include <QStandardPaths> | 6 | #include <QStandardPaths> |
7 | #include <QTimer> | 7 | #include <QTimer> |
8 | #include <QDebug> | 8 | #include <QDebug> |
9 | #include <QEventLoop> | ||
9 | #include <functional> | 10 | #include <functional> |
10 | 11 | ||
11 | namespace async { | 12 | namespace async { |
@@ -64,6 +65,14 @@ namespace async { | |||
64 | * The future side for the client. | 65 | * The future side for the client. |
65 | * | 66 | * |
66 | * It does not directly hold the state. | 67 | * It does not directly hold the state. |
68 | * | ||
69 | * The advantage of this is that we can specialize it to: | ||
70 | * * do inline transformations to the data | ||
71 | * * directly store the state in a suitable datastructure: QList, QSet, std::list, QVector, ... | ||
72 | * * build async interfaces with signals | ||
73 | * * build sync interfaces that block when accessing the value | ||
74 | * | ||
75 | * TODO: This should probably be merged with daniels futurebase used in Async | ||
67 | */ | 76 | */ |
68 | template<class DomainType> | 77 | template<class DomainType> |
69 | class ResultEmitter { | 78 | class ResultEmitter { |
@@ -85,6 +94,42 @@ namespace async { | |||
85 | std::function<void(void)> completeHandler; | 94 | std::function<void(void)> completeHandler; |
86 | }; | 95 | }; |
87 | 96 | ||
97 | |||
98 | /* | ||
99 | * A result set specialization that provides a syncronous list | ||
100 | */ | ||
101 | template<class T> | ||
102 | class SyncListResult : public QList<T> { | ||
103 | public: | ||
104 | SyncListResult(const QSharedPointer<ResultEmitter<T> > &emitter) | ||
105 | :QList<T>(), | ||
106 | mComplete(false), | ||
107 | mEmitter(emitter) | ||
108 | { | ||
109 | emitter->onAdded([this](const T &value) { | ||
110 | this->append(value); | ||
111 | }); | ||
112 | emitter->onComplete([this]() { | ||
113 | mComplete = true; | ||
114 | auto loop = mWaitLoop.toStrongRef(); | ||
115 | if (loop) { | ||
116 | loop->quit(); | ||
117 | } | ||
118 | }); | ||
119 | } | ||
120 | |||
121 | void exec() | ||
122 | { | ||
123 | auto loop = QSharedPointer<QEventLoop>::create(); | ||
124 | mWaitLoop = loop; | ||
125 | loop->exec(QEventLoop::ExcludeUserInputEvents); | ||
126 | } | ||
127 | |||
128 | private: | ||
129 | bool mComplete; | ||
130 | QWeakPointer<QEventLoop> mWaitLoop; | ||
131 | QSharedPointer<ResultEmitter<T> > mEmitter; | ||
132 | }; | ||
88 | } | 133 | } |
89 | 134 | ||
90 | namespace Akonadi2 { | 135 | namespace Akonadi2 { |
diff --git a/client/test/clientapitest.cpp b/client/test/clientapitest.cpp index bff910b..2d1c238 100644 --- a/client/test/clientapitest.cpp +++ b/client/test/clientapitest.cpp | |||
@@ -37,15 +37,9 @@ private Q_SLOTS: | |||
37 | Akonadi2::Query query; | 37 | Akonadi2::Query query; |
38 | query.resources << "dummyresource"; | 38 | query.resources << "dummyresource"; |
39 | 39 | ||
40 | auto result = Akonadi2::Store::load<Akonadi2::Domain::Event>(query); | 40 | async::SyncListResult<Akonadi2::Domain::Event::Ptr> result(Akonadi2::Store::load<Akonadi2::Domain::Event>(query)); |
41 | 41 | result.exec(); | |
42 | QList<Akonadi2::Domain::Event::Ptr> resultSet; | 42 | QCOMPARE(result.size(), 1); |
43 | result->onAdded([&resultSet](const Akonadi2::Domain::Event::Ptr &event){ resultSet << event; qDebug() << "result added";}); | ||
44 | |||
45 | bool complete; | ||
46 | result->onComplete([&complete]{ complete = true; qDebug() << "complete";}); | ||
47 | |||
48 | QTRY_VERIFY(complete); | ||
49 | } | 43 | } |
50 | 44 | ||
51 | }; | 45 | }; |