|
1 |
| -#ifndef INC_PROMISE_QT_CPP_ |
2 |
| -#define INC_PROMISE_QT_CPP_ |
3 |
| - |
4 |
| -/* |
5 |
| - * Copyright (c) 2021, xhawk18 |
6 |
| - * at gmail.com |
7 |
| - * |
8 |
| - * The MIT License (MIT) |
9 |
| - * |
10 |
| - * Permission is hereby granted, free of charge, to any person obtaining a copy |
11 |
| - * of this software and associated documentation files (the "Software"), to deal |
12 |
| - * in the Software without restriction, including without limitation the rights |
13 |
| - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
14 |
| - * copies of the Software, and to permit persons to whom the Software is |
15 |
| - * furnished to do so, subject to the following conditions: |
16 |
| - * |
17 |
| - * The above copyright notice and this permission notice shall be included in |
18 |
| - * all copies or substantial portions of the Software. |
19 |
| - * |
20 |
| - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
21 |
| - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
22 |
| - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
23 |
| - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
24 |
| - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
25 |
| - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
26 |
| - * THE SOFTWARE. |
27 |
| - */ |
28 |
| - |
29 |
| -// |
30 |
| -// Promisified timer based on promise-cpp and QT |
31 |
| -// |
32 |
| -// Functions -- |
33 |
| -// Promise yield(QWidget *widget); |
34 |
| -// Promise delay(QWidget *widget, uint64_t time_ms); |
35 |
| -// void cancelDelay(Promise promise); |
36 |
| -// |
37 |
| -// Promise setTimeout(QWidget *widget, |
38 |
| -// const std::function<void(bool /*cancelled*/)> &func, |
39 |
| -// uint64_t time_ms); |
40 |
| -// void clearTimeout(Promise promise); |
41 |
| -// |
42 |
| - |
43 |
| -#include "promise-cpp/promise.hpp" |
44 |
| -#include "promise_qt.hpp" |
45 |
| -#include <chrono> |
46 |
| -#include <QObject> |
47 |
| -#include <QTimerEvent> |
48 |
| -#include <QApplication> |
49 |
| - |
50 |
| -namespace promise { |
51 |
| - |
52 |
| -PromiseEventFilter::PromiseEventFilter() {} |
53 |
| - |
54 |
| -PromiseEventFilter::Listeners::iterator PromiseEventFilter::addEventListener(QObject *object, QEvent::Type eventType, const std::function<bool(QObject *, QEvent *)> &func) { |
55 |
| - std::pair<QObject *, QEvent::Type> key = { object, eventType }; |
56 |
| - return listeners_.insert({ key, func }); |
57 |
| -} |
58 |
| - |
59 |
| -void PromiseEventFilter::removeEventListener(PromiseEventFilter::Listeners::iterator itr) { |
60 |
| - listeners_.erase(itr); |
61 |
| -} |
62 |
| - |
63 |
| -PromiseEventFilter &PromiseEventFilter::getSingleInstance() { |
64 |
| - static PromiseEventFilter promiseEventFilter; |
65 |
| - return promiseEventFilter; |
66 |
| -} |
67 |
| - |
68 |
| -bool PromiseEventFilter::eventFilter(QObject *object, QEvent *event) { |
69 |
| - std::pair<QObject *, QEvent::Type> key = { object, event->type() }; |
70 |
| - |
71 |
| - //LOG_INFO("eventFilter = {} {}", object, event->type()); |
72 |
| - // may not safe if one handler is removed by other |
73 |
| - std::list<Listeners::iterator> itrs; |
74 |
| - for (Listeners::iterator itr = listeners_.lower_bound(key); |
75 |
| - itr != listeners_.end() && key == itr->first; ++itr) { |
76 |
| - itrs.push_back(itr); |
77 |
| - } |
78 |
| - for (Listeners::iterator itr : itrs) { |
79 |
| - itr->second(object, event); |
80 |
| - } |
81 |
| - |
82 |
| - if (event->type() == QEvent::Destroy) { |
83 |
| - removeObjectFilters(object); |
84 |
| - } |
85 |
| - |
86 |
| - return QObject::eventFilter(object, event); |
87 |
| -} |
88 |
| - |
89 |
| -bool PromiseEventFilter::removeObjectFilters(QObject *object) { |
90 |
| - std::pair<QObject *, QEvent::Type> key = { object, QEvent::None }; |
91 |
| - |
92 |
| - // checked one by one for safety (others may be removed) |
93 |
| - while (true) { |
94 |
| - Listeners::iterator itr = listeners_.lower_bound(key); |
95 |
| - if (itr != listeners_.end() && itr->first.first == object) { |
96 |
| - itr->second(object, nullptr); |
97 |
| - } |
98 |
| - else { |
99 |
| - break; |
100 |
| - } |
101 |
| - } |
102 |
| - |
103 |
| - return false; |
104 |
| -} |
105 |
| - |
106 |
| -// Wait event will wait the event for only once |
107 |
| -Promise waitEvent(QObject *object, |
108 |
| - QEvent::Type eventType, |
109 |
| - bool callSysHandler) { |
110 |
| - auto listener = std::make_shared<PromiseEventFilter::Listeners::iterator>(); |
111 |
| - Promise promise = newPromise([listener, object, eventType, callSysHandler](Defer &defer) { |
112 |
| - |
113 |
| - std::shared_ptr<bool> disableFilter = std::make_shared<bool>(false); |
114 |
| - //PTI; |
115 |
| - *listener = PromiseEventFilter::getSingleInstance().addEventListener( |
116 |
| - object, eventType, [defer, callSysHandler, disableFilter](QObject *object, QEvent *event) { |
117 |
| - (void)object; |
118 |
| - if (event == nullptr) { |
119 |
| - defer.reject(); |
120 |
| - return false; |
121 |
| - } |
122 |
| - // The next then function will be call immediately |
123 |
| - // Be care that do not use event in the next event loop |
124 |
| - else if (*disableFilter) { |
125 |
| - return false; |
126 |
| - } |
127 |
| - else if (callSysHandler) { |
128 |
| - //PTI; |
129 |
| - *disableFilter = true; |
130 |
| - QApplication::sendEvent(object, event); |
131 |
| - *disableFilter = false; |
132 |
| - defer.resolve(event); |
133 |
| - return true; |
134 |
| - } |
135 |
| - else { |
136 |
| - //PTI; |
137 |
| - defer.resolve(event); |
138 |
| - return false; |
139 |
| - } |
140 |
| - } |
141 |
| - ); |
142 |
| - }).finally([listener]() { |
143 |
| - //PTI; |
144 |
| - PromiseEventFilter::getSingleInstance().removeEventListener(*listener); |
145 |
| - }); |
146 |
| - |
147 |
| - return promise; |
148 |
| -} |
149 |
| - |
150 |
| - |
151 |
| -QtTimerHolder::QtTimerHolder() { |
152 |
| -} |
153 |
| - |
154 |
| -QtTimerHolder::~QtTimerHolder() { |
155 |
| -} |
156 |
| - |
157 |
| -Promise QtTimerHolder::delay(int time_ms) { |
158 |
| - int timerId = getInstance().startTimer(time_ms); |
159 |
| - |
160 |
| - return newPromise([timerId](Defer &defer) { |
161 |
| - getInstance().defers_.insert({ timerId, defer }); |
162 |
| - }).finally([timerId]() { |
163 |
| - getInstance().killTimer(timerId); |
164 |
| - getInstance().defers_.erase(timerId); |
165 |
| - }); |
166 |
| -} |
167 |
| - |
168 |
| -Promise QtTimerHolder::yield() { |
169 |
| - return delay(0); |
170 |
| -} |
171 |
| - |
172 |
| -Promise QtTimerHolder::setTimeout(const std::function<void(bool)> &func, |
173 |
| - int time_ms) { |
174 |
| - return delay(time_ms).then([func]() { |
175 |
| - func(false); |
176 |
| - }, [func]() { |
177 |
| - func(true); |
178 |
| - }); |
179 |
| -} |
180 |
| - |
181 |
| -void QtTimerHolder::timerEvent(QTimerEvent *event) { |
182 |
| - int timerId = event->timerId(); |
183 |
| - auto found = this->defers_.find(timerId); |
184 |
| - if (found != this->defers_.end()) { |
185 |
| - Defer &defer = found->second; |
186 |
| - defer.resolve(); |
187 |
| - } |
188 |
| - QObject::timerEvent(event); |
189 |
| -} |
190 |
| - |
191 |
| -QtTimerHolder &QtTimerHolder::getInstance() { |
192 |
| - static QtTimerHolder s_qtTimerHolder_; |
193 |
| - return s_qtTimerHolder_; |
194 |
| -} |
195 |
| - |
196 |
| -Promise delay(int time_ms) { |
197 |
| - return QtTimerHolder::delay(time_ms); |
198 |
| -} |
199 |
| - |
200 |
| -Promise yield() { |
201 |
| - return QtTimerHolder::yield(); |
202 |
| -} |
203 |
| - |
204 |
| -Promise setTimeout(const std::function<void(bool)> &func, |
205 |
| - int time_ms) { |
206 |
| - return QtTimerHolder::setTimeout(func, time_ms); |
207 |
| -} |
208 |
| - |
209 |
| - |
210 |
| -void cancelDelay(Promise promise) { |
211 |
| - promise.reject(); |
212 |
| -} |
213 |
| - |
214 |
| -void clearTimeout(Promise promise) { |
215 |
| - cancelDelay(promise); |
216 |
| -} |
217 |
| - |
218 |
| -} |
219 | 1 |
|
| 2 | +#ifndef PROMISE_HEADONLY |
| 3 | +#include "promise_qt_inl.hpp" |
220 | 4 | #endif
|
| 5 | + |
0 commit comments