Merge lp:~unity-api-team/indicator-network/fix-gmainloop-syncing into lp:indicator-network/14.09
- fix-gmainloop-syncing
- Merge into trunk.14.09
Status: | Merged | ||||||||
---|---|---|---|---|---|---|---|---|---|
Approved by: | Marcus Tomlinson | ||||||||
Approved revision: | 469 | ||||||||
Merged at revision: | 462 | ||||||||
Proposed branch: | lp:~unity-api-team/indicator-network/fix-gmainloop-syncing | ||||||||
Merge into: | lp:indicator-network/14.09 | ||||||||
Prerequisite: | lp:~unity-api-team/indicator-network/increase-dbus-timeouts | ||||||||
Diff against target: |
1839 lines (+662/-302) 34 files modified
src/connectivity-cpp/dbus-cpp/services/nm.h (+2/-11) src/connectivity-cpp/src/platform/nmofono/manager.cpp (+45/-40) src/connectivity-cpp/src/platform/nmofono/manager.h (+4/-0) src/connectivity-cpp/src/platform/nmofono/wifi/access-point.cpp (+21/-12) src/connectivity-cpp/src/platform/nmofono/wifi/access-point.h (+49/-3) src/connectivity-cpp/src/platform/nmofono/wifi/grouped-access-point.cpp (+5/-5) src/connectivity-cpp/src/platform/nmofono/wifi/grouped-access-point.h (+1/-2) src/connectivity-cpp/src/platform/nmofono/wifi/link.cpp (+19/-61) src/indicator/CMakeLists.txt (+2/-3) src/indicator/connectivity-service/connectivity-service.cpp (+21/-5) src/indicator/connectivity-service/connectivity-service.h (+4/-1) src/indicator/indicator-network-service.cpp (+2/-0) src/indicator/menuitems/access-point-item.cpp (+64/-49) src/indicator/menuitems/access-point-item.h (+44/-0) src/indicator/modem-manager.cpp (+17/-5) src/indicator/modem-manager.h (+11/-1) src/indicator/modem.cpp (+114/-34) src/indicator/modem.h (+4/-1) src/indicator/quick-access-section.cpp (+23/-11) src/indicator/quick-access-section.h (+4/-1) src/indicator/root-state.cpp (+38/-9) src/indicator/root-state.h (+4/-1) src/indicator/sim-unlock-dialog.h (+3/-0) src/indicator/wifi-link-item.cpp (+51/-22) src/indicator/wifi-link-item.h (+43/-0) src/indicator/wifi-section.cpp (+32/-8) src/indicator/wifi-section.h (+1/-1) src/indicator/wwan-link-item.cpp (+10/-2) src/indicator/wwan-section.cpp (+8/-1) src/indicator/wwan-section.h (+1/-1) src/menumodel-cpp/gio-helpers/util.cpp (+10/-10) src/menumodel-cpp/gio-helpers/util.h (+2/-2) tests/unit/indicator/menuitems/CMakeLists.txt (+1/-0) tests/unit/indicator/menuitems/test-access-point-item.cpp (+2/-0) |
||||||||
To merge this branch: | bzr merge lp:~unity-api-team/indicator-network/fix-gmainloop-syncing | ||||||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Marcus Tomlinson (community) | Approve | ||
Charles Kerr (community) | Approve | ||
Review via email: mp+240044@code.launchpad.net |
Commit message
* Fix GMainLoopDispatch dispatching ordering when
called inside GMainLoop already
* Fix GMainLoopDispatch locking
* Force all signals from external (dbus-cpp) threads through
GMainLoopDispatch
Description of the change
Antti Kaijanmäki (kaijanmaki) wrote : | # |
> The "big picture" is this is a step in the right direction and my vote is to
> approve. I don't like the technical debt being accrued here, but it's
> preferable to blocking Criticals on an even larger megapatch.
The MP tries to do minimal changes, but yet introduce the dispatching of all external signals through GMainLoopDispatch.
> First, The "shared pimpl" idiom of thread safety here is interesting. It's
> generic enough that it can be (and is) applied liberally here, so that's
> useful. TBH though, it doesn't make sense to keep processing these signals
> after the outer object's been destroyed and I would have preferred another
> solution, e.g. GMainLoopDispatch's destructor calling g_signal_remove() after
> checking a lock guard to confirm that the func wasn't being called at the same
> time.
please note that GMainLoopDispatch is not a long living object. It's destructor is not usable for virtually anything.
GMainLoopDispatch is destroyed as soon as it gets out of scope in which it was created. It only exists to offer easy interface to the static variables inside menumodel-
> Second, the new comments sprinkled through the code "this must be called from
> GMainLoop", "these signals are already synced in main loop" etc. are red
> flags. There are a lot of them and they're hard to test... if there's no code
> making incorrect calls now (and how would we know for certian?) there surely
> will be in the future. I'd rather see either (a) a compile-time test of some
> kind, although I don't know how that would work, or (b) consistent thread
> rules applied through the code so that everyone knows what the rules of the
> road are.
Yes. the problem here is that the code base did not rely on GMainLoop being around at all. This is the first step to more widely utilize GMainLoop. It's already agreed that we will create certain assertion directive that checks it is being called from GMainLoop main context. This directive can then be slapped through the codebase to verify that the precondition holds.
> Third, many of the ScopedConnections created by connect() are dropped on the
> floor. Since these connections' lambdas hold handles to the pimpl shared_ptrs,
The only lambdas holding pimpl shared_ptrs are the ones passed to GMainLoopDispatch and the lambdas are free'ed as soon as the dispatching is done.
> we need to be more careful about disconnecting them when the public objects
> are destroyed. My concern is that we don't wind up with ghost object chains
> that continue to process each other's signals.
We share the same concern. Next step on robusting the code base is to indeed to vefiry the lifecycles. Any connections that there are now in place or are missing are coming from the code base prior of this MP. And verifying and fixing possible issues is left for next iteration to keep the MP size and mental burden down.
> Lastly (and superficially), I'd also like to see GMainLoopDispatch renamed
> MainLoopDispatch, since there's nothing intrinsic to glib about the idea. :)
here we go again... ;)
Marcus Tomlinson (marcustomlinson) wrote : | # |
Tested this on mako rtm 115, and it does fix the linked bug. Next we should scan through the rest of the code for callbacks that could arrive on external threads (E.g. service side writable properties whose 'changed' signals are emitted from the dbus-cpp thread)
- 468. By Antti Kaijanmäki
-
races races all the way..
- 469. By Antti Kaijanmäki
-
blah..
Preview Diff
1 | === modified file 'src/connectivity-cpp/dbus-cpp/services/nm.h' |
2 | --- src/connectivity-cpp/dbus-cpp/services/nm.h 2014-10-31 14:07:40 +0000 |
3 | +++ src/connectivity-cpp/dbus-cpp/services/nm.h 2014-10-31 14:07:40 +0000 |
4 | @@ -911,7 +911,7 @@ |
5 | return result.value(); |
6 | } |
7 | |
8 | - std::vector<Device> get_devices() |
9 | + std::vector<core::dbus::types::ObjectPath> get_devices() |
10 | { |
11 | auto result = |
12 | object->invoke_method_synchronously< |
13 | @@ -921,16 +921,7 @@ |
14 | if (result.is_error()) |
15 | connectivity::throw_dbus_exception(result.error()); |
16 | |
17 | - std::vector<Device> devices; |
18 | - for (const auto& path : result.value()) |
19 | - { |
20 | - devices.emplace_back( |
21 | - Device( |
22 | - service, |
23 | - service->object_for_path(path))); |
24 | - } |
25 | - |
26 | - return devices; |
27 | + return result.value(); |
28 | } |
29 | |
30 | NetworkManager(std::shared_ptr<core::dbus::Service> &service, |
31 | |
32 | === modified file 'src/connectivity-cpp/src/platform/nmofono/manager.cpp' |
33 | --- src/connectivity-cpp/src/platform/nmofono/manager.cpp 2014-10-09 10:58:30 +0000 |
34 | +++ src/connectivity-cpp/src/platform/nmofono/manager.cpp 2014-10-31 14:07:40 +0000 |
35 | @@ -172,29 +172,11 @@ |
36 | p->urfkill->switches[fdo::URfkill::Interface::Killswitch::Type::wlan]); |
37 | p->m_wifiKillSwitch->state().changed().connect(std::bind(&Private::updateHasWifi, p.get())); |
38 | |
39 | - p->nm->device_added->connect([this](const dbus::types::ObjectPath &path){ |
40 | -#ifdef INDICATOR_NETWORK_TRACE_MESSAGES |
41 | - std::cout << "Device Added:" << path.as_string() << std::endl; |
42 | -#endif |
43 | - auto links = p->m_links.get(); |
44 | - for (const auto &dev : links) { |
45 | - if (std::dynamic_pointer_cast<wifi::Link>(dev)->device_path() == path) { |
46 | - // already in the list |
47 | - return; |
48 | - } |
49 | - } |
50 | - |
51 | - NM::Interface::Device dev(p->nm->service, |
52 | - p->nm->service->object_for_path(path)); |
53 | - if (dev.type() == NM::Interface::Device::Type::wifi) { |
54 | - links.insert(std::make_shared<wifi::Link>(dev, |
55 | - *p->nm.get(), |
56 | - p->m_wifiKillSwitch)); |
57 | - p->m_links.set(links); |
58 | - } |
59 | - |
60 | - p->updateHasWifi(); |
61 | - }); |
62 | + p->nm->device_added->connect(std::bind(&Manager::device_added, this, std::placeholders::_1)); |
63 | + for(const auto &path : p->nm->get_devices()) { |
64 | + device_added(path); |
65 | + } |
66 | + |
67 | p->nm->device_removed->connect([this](const dbus::types::ObjectPath &path){ |
68 | #ifdef INDICATOR_NETWORK_TRACE_MESSAGES |
69 | std::cout << "Device Removed:" << path.as_string() << std::endl; |
70 | @@ -210,23 +192,6 @@ |
71 | |
72 | p->updateHasWifi(); |
73 | }); |
74 | - std::set<std::shared_ptr<networking::Link> > links; |
75 | - for(auto dev : p->nm->get_devices()) { |
76 | - switch (dev.type()) { |
77 | - case NM::Interface::Device::Type::wifi: |
78 | - { |
79 | - std::shared_ptr<networking::Link> link; |
80 | - link.reset(new wifi::Link(dev, |
81 | - *p->nm.get(), |
82 | - p->m_wifiKillSwitch)); |
83 | - links.insert(link); |
84 | - break; |
85 | - } |
86 | - default: |
87 | - ; |
88 | - } |
89 | - } |
90 | - p->m_links.set(links); |
91 | |
92 | updateNetworkingStatus(p->nm->state->get()); |
93 | p->nm->properties_changed->connect([this](NM::Interface::NetworkManager::Signal::PropertiesChanged::ArgumentType map) { |
94 | @@ -259,6 +224,46 @@ |
95 | } |
96 | |
97 | void |
98 | +Manager::device_added(const dbus::types::ObjectPath &path) |
99 | +{ |
100 | +#ifdef INDICATOR_NETWORK_TRACE_MESSAGES |
101 | + std::cout << "Device Added:" << path.as_string() << std::endl; |
102 | +#endif |
103 | + auto links = p->m_links.get(); |
104 | + |
105 | + for (const auto &dev : links) { |
106 | + if (std::dynamic_pointer_cast<wifi::Link>(dev)->device_path() == path) { |
107 | + // already in the list |
108 | + return; |
109 | + } |
110 | + } |
111 | + |
112 | + connectivity::networking::Link::Ptr link; |
113 | + try { |
114 | + NM::Interface::Device dev(p->nm->service, |
115 | + p->nm->service->object_for_path(path)); |
116 | + if (dev.type() == NM::Interface::Device::Type::wifi) { |
117 | + link = std::make_shared<wifi::Link>(dev, |
118 | + *p->nm.get(), |
119 | + p->m_wifiKillSwitch); |
120 | + } |
121 | + } catch (const std::exception &e) { |
122 | + std::cerr << __PRETTY_FUNCTION__ << ": failed to create Device proxy for "<< path.as_string() << ": " << std::endl |
123 | + << "\t" << e.what() << std::endl |
124 | + << "\tIgnoring." << std::endl; |
125 | + return; |
126 | + } |
127 | + |
128 | + if (link) { |
129 | + links.insert(link); |
130 | + p->m_links.set(links); |
131 | + } |
132 | + |
133 | + p->updateHasWifi(); |
134 | +} |
135 | + |
136 | + |
137 | +void |
138 | Manager::enableFlightMode() |
139 | { |
140 | #ifdef INDICATOR_NETWORK_TRACE_MESSAGES |
141 | |
142 | === modified file 'src/connectivity-cpp/src/platform/nmofono/manager.h' |
143 | --- src/connectivity-cpp/src/platform/nmofono/manager.h 2014-09-25 00:06:12 +0000 |
144 | +++ src/connectivity-cpp/src/platform/nmofono/manager.h 2014-10-31 14:07:40 +0000 |
145 | @@ -20,6 +20,7 @@ |
146 | #define PLATFORM_NMOFONO_MANAGER |
147 | |
148 | #include <connectivity/networking/manager.h> |
149 | +#include <core/dbus/types/object_path.h> |
150 | |
151 | namespace core { |
152 | namespace dbus { |
153 | @@ -61,6 +62,9 @@ |
154 | const core::Property<std::set<std::shared_ptr<connectivity::networking::Service>>>&services() const override; |
155 | const core::Property<connectivity::networking::Manager::NetworkingStatus> & status() const override; |
156 | const core::Property<std::uint32_t>& characteristics() const override; |
157 | + |
158 | +private: |
159 | + void device_added(const core::dbus::types::ObjectPath &path); |
160 | }; |
161 | |
162 | #endif |
163 | |
164 | === modified file 'src/connectivity-cpp/src/platform/nmofono/wifi/access-point.cpp' |
165 | --- src/connectivity-cpp/src/platform/nmofono/wifi/access-point.cpp 2014-08-22 12:18:55 +0000 |
166 | +++ src/connectivity-cpp/src/platform/nmofono/wifi/access-point.cpp 2014-10-31 14:07:40 +0000 |
167 | @@ -34,11 +34,11 @@ |
168 | |
169 | std::string ssid; |
170 | // Note: raw_ssid is _not_ guaranteed to be null terminated. |
171 | - const std::vector<std::int8_t> &raw_ssid = m_ap.ssid->get(); |
172 | - if(g_utf8_validate((const char*)(&raw_ssid[0]), raw_ssid.size(), nullptr)) { |
173 | - ssid = std::string(raw_ssid.begin(), raw_ssid.end()); |
174 | + m_raw_ssid = m_ap.ssid->get(); |
175 | + if(g_utf8_validate((const char*)(&m_raw_ssid[0]), m_raw_ssid.size(), nullptr)) { |
176 | + ssid = std::string(m_raw_ssid.begin(), m_raw_ssid.end()); |
177 | } else { |
178 | - for (auto c : m_ap.ssid->get()) { |
179 | + for (auto c : m_raw_ssid) { |
180 | if (isprint(c)) { |
181 | ssid += (char)c; |
182 | } else { |
183 | @@ -58,6 +58,15 @@ |
184 | } |
185 | } |
186 | }); |
187 | + |
188 | + m_flags = m_ap.flags->get(); |
189 | + /* NetworkManager seems to set the wpa and rns flags |
190 | + * for AccessPoints on the same network in a total random manner. |
191 | + * Sometimes only wpa_flags or rns_flags is set and sometimes |
192 | + * they both are set but always to the same value |
193 | + */ |
194 | + m_secflags = m_ap.wpa_flags->get()|m_ap.rsn_flags->get(); |
195 | + m_mode = m_ap.mode->get(); |
196 | } |
197 | |
198 | const core::dbus::types::ObjectPath AccessPoint::object_path() const { |
199 | @@ -79,6 +88,11 @@ |
200 | return m_ssid; |
201 | } |
202 | |
203 | +const std::vector<std::int8_t>& AccessPoint::raw_ssid() const |
204 | +{ |
205 | + return m_raw_ssid; |
206 | +} |
207 | + |
208 | bool AccessPoint::secured() const |
209 | { |
210 | return m_secured; |
211 | @@ -93,14 +107,9 @@ |
212 | if(this == &other) |
213 | return true; |
214 | return m_ssid == other.m_ssid && |
215 | - m_ap.flags->get() == other.m_ap.flags->get() && |
216 | - /* NetworkManager seems to set the wpa and rns flags |
217 | - * for AccessPoints on the same network in a total random manner. |
218 | - * Sometimes only wpa_flags or rns_flags is set and sometimes |
219 | - * they both are set but always to the same value |
220 | - */ |
221 | - (m_ap.wpa_flags->get()|m_ap.rsn_flags->get()) == (other.m_ap.wpa_flags->get()|other.m_ap.rsn_flags->get()) && |
222 | - m_ap.mode->get() == other.m_ap.mode->get(); |
223 | + m_flags == other.m_flags && |
224 | + m_secflags == other.m_secflags && |
225 | + m_mode == other.m_mode; |
226 | } |
227 | |
228 | } |
229 | |
230 | === modified file 'src/connectivity-cpp/src/platform/nmofono/wifi/access-point.h' |
231 | --- src/connectivity-cpp/src/platform/nmofono/wifi/access-point.h 2014-08-19 19:55:15 +0000 |
232 | +++ src/connectivity-cpp/src/platform/nmofono/wifi/access-point.h 2014-10-31 14:07:40 +0000 |
233 | @@ -40,10 +40,52 @@ |
234 | |
235 | class AccessPoint : public connectivity::networking::wifi::AccessPoint |
236 | { |
237 | - |
238 | public: |
239 | typedef std::shared_ptr<AccessPoint> Ptr; |
240 | |
241 | + struct Key { |
242 | + std::string ssid; |
243 | + uint32_t flags; |
244 | + uint32_t secflags; |
245 | + uint32_t mode; |
246 | + |
247 | + bool operator<(const Key &other) const |
248 | + { |
249 | + // Standard lexigraphic comparison. |
250 | + if(ssid < other.ssid) |
251 | + return true; |
252 | + if(ssid > other.ssid) |
253 | + return false; |
254 | + |
255 | + if(flags < other.flags) |
256 | + return true; |
257 | + if(flags > other.flags) |
258 | + return false; |
259 | + |
260 | + if(secflags < other.secflags) |
261 | + return true; |
262 | + if(secflags > secflags) |
263 | + return false; |
264 | + |
265 | + if(mode < other.mode) |
266 | + return true; |
267 | + if(mode > other.mode) |
268 | + return false; |
269 | + return false; |
270 | + } |
271 | + |
272 | + Key() = delete; |
273 | + Key(const AccessPoint::Ptr &curap) |
274 | + { |
275 | + ssid = curap->ssid(); |
276 | + flags = curap->m_flags; |
277 | + secflags = curap->m_secflags; |
278 | + mode = curap->m_mode; |
279 | + } |
280 | + }; |
281 | + friend class Key; |
282 | + |
283 | + |
284 | AccessPoint(const org::freedesktop::NetworkManager::Interface::AccessPoint &ap); |
285 | const core::Property<double>& strength() const; |
286 | virtual ~AccessPoint() = default; |
287 | @@ -54,6 +96,7 @@ |
288 | const core::Property<std::chrono::system_clock::time_point>& lastConnected() const; |
289 | |
290 | const std::string& ssid() const override; |
291 | + const std::vector<std::int8_t>& raw_ssid() const; |
292 | |
293 | bool secured() const override; |
294 | |
295 | @@ -61,8 +104,6 @@ |
296 | |
297 | const core::dbus::types::ObjectPath object_path() const; |
298 | |
299 | - const org::freedesktop::NetworkManager::Interface::AccessPoint& get_ap() const { return m_ap; } |
300 | - |
301 | bool operator==(const platform::nmofono::wifi::AccessPoint &other) const; |
302 | bool operator!=(const platform::nmofono::wifi::AccessPoint &other) const { return !(*this == other); }; |
303 | |
304 | @@ -71,8 +112,13 @@ |
305 | core::Property<std::chrono::system_clock::time_point> m_lastConnected; |
306 | org::freedesktop::NetworkManager::Interface::AccessPoint m_ap; |
307 | std::string m_ssid; |
308 | + std::vector<std::int8_t> m_raw_ssid; |
309 | bool m_secured; |
310 | bool m_adhoc; |
311 | + |
312 | + std::uint32_t m_flags; |
313 | + std::uint32_t m_secflags; |
314 | + std::uint32_t m_mode; |
315 | }; |
316 | |
317 | } |
318 | |
319 | === modified file 'src/connectivity-cpp/src/platform/nmofono/wifi/grouped-access-point.cpp' |
320 | --- src/connectivity-cpp/src/platform/nmofono/wifi/grouped-access-point.cpp 2014-10-09 10:58:30 +0000 |
321 | +++ src/connectivity-cpp/src/platform/nmofono/wifi/grouped-access-point.cpp 2014-10-31 14:07:40 +0000 |
322 | @@ -156,11 +156,6 @@ |
323 | return p->aplist.at(0)->object_path(); |
324 | } |
325 | |
326 | -const org::freedesktop::NetworkManager::Interface::AccessPoint& GroupedAccessPoint::get_ap() const { |
327 | - std::lock_guard<std::mutex> l(p->m); |
328 | - return p->aplist.at(0)->get_ap(); |
329 | -} |
330 | - |
331 | const core::Property<double>& GroupedAccessPoint::strength() const |
332 | { |
333 | std::lock_guard<std::mutex> l(p->m); |
334 | @@ -177,7 +172,12 @@ |
335 | { |
336 | std::lock_guard<std::mutex> l(p->m); |
337 | return p->aplist.at(0)->ssid(); |
338 | +} |
339 | |
340 | +const std::vector<std::int8_t>& GroupedAccessPoint::raw_ssid() const |
341 | +{ |
342 | + std::lock_guard<std::mutex> l(p->m); |
343 | + return p->aplist.at(0)->raw_ssid(); |
344 | } |
345 | |
346 | bool GroupedAccessPoint::secured() const |
347 | |
348 | === modified file 'src/connectivity-cpp/src/platform/nmofono/wifi/grouped-access-point.h' |
349 | --- src/connectivity-cpp/src/platform/nmofono/wifi/grouped-access-point.h 2014-08-19 19:55:15 +0000 |
350 | +++ src/connectivity-cpp/src/platform/nmofono/wifi/grouped-access-point.h 2014-10-31 14:07:40 +0000 |
351 | @@ -57,6 +57,7 @@ |
352 | const core::Property<std::chrono::system_clock::time_point>& lastConnected() const; |
353 | |
354 | const std::string& ssid() const override; |
355 | + const std::vector<std::int8_t>& raw_ssid() const; |
356 | |
357 | bool secured() const override; |
358 | |
359 | @@ -64,8 +65,6 @@ |
360 | |
361 | const core::dbus::types::ObjectPath object_path() const; |
362 | |
363 | - const org::freedesktop::NetworkManager::Interface::AccessPoint& get_ap() const; |
364 | - |
365 | void add_ap(std::shared_ptr<platform::nmofono::wifi::AccessPoint> &ap); |
366 | void remove_ap(std::shared_ptr<platform::nmofono::wifi::AccessPoint> &ap); |
367 | int num_aps() const; |
368 | |
369 | === modified file 'src/connectivity-cpp/src/platform/nmofono/wifi/link.cpp' |
370 | --- src/connectivity-cpp/src/platform/nmofono/wifi/link.cpp 2014-10-09 10:58:30 +0000 |
371 | +++ src/connectivity-cpp/src/platform/nmofono/wifi/link.cpp 2014-10-31 14:07:40 +0000 |
372 | @@ -30,58 +30,6 @@ |
373 | |
374 | using core::Property; |
375 | |
376 | -struct AccessPointKey { |
377 | - std::string ssid; |
378 | - uint32_t flags; |
379 | - uint32_t wpa_flags; |
380 | - uint32_t rsn_flags; |
381 | - uint32_t mode; |
382 | - |
383 | - bool operator<(const AccessPointKey &other) const |
384 | - { |
385 | - // Standard lexigraphic comparison. |
386 | - if(ssid < other.ssid) |
387 | - return true; |
388 | - if(ssid > other.ssid) |
389 | - return false; |
390 | - |
391 | - if(flags < other.flags) |
392 | - return true; |
393 | - if(flags > other.flags) |
394 | - return false; |
395 | - |
396 | - /* NetworkManager seems to set the wpa and rns flags |
397 | - * for AccessPoints on the same network in a total random manner. |
398 | - * Sometimes only wpa_flags or rns_flags is set and sometimes |
399 | - * they both are set but always to the same value |
400 | - */ |
401 | - if((wpa_flags|rsn_flags) < (other.wpa_flags|other.rsn_flags)) |
402 | - return true; |
403 | - if((wpa_flags|rsn_flags) > (other.wpa_flags|other.rsn_flags)) |
404 | - return false; |
405 | - |
406 | - if(mode < other.mode) |
407 | - return true; |
408 | - if(mode > other.mode) |
409 | - return false; |
410 | - return false; |
411 | - } |
412 | -}; |
413 | - |
414 | -namespace { |
415 | - |
416 | -AccessPointKey build_key(const std::shared_ptr<platform::nmofono::wifi::AccessPoint> &curap) |
417 | -{ |
418 | - AccessPointKey k; |
419 | - k.ssid = curap->ssid(); |
420 | - k.flags = curap->get_ap().flags->get(); |
421 | - k.wpa_flags = curap->get_ap().wpa_flags->get(); |
422 | - k.rsn_flags = curap->get_ap().rsn_flags->get(); |
423 | - k.mode = curap->get_ap().mode->get(); |
424 | - return k; |
425 | -} |
426 | - |
427 | -} |
428 | |
429 | struct Link::Private |
430 | { |
431 | @@ -103,7 +51,7 @@ |
432 | // hack hack |
433 | std::vector<core::ScopedConnection> switchConnection; |
434 | |
435 | - std::map<AccessPointKey, std::shared_ptr<GroupedAccessPoint>> grouper; |
436 | + std::map<AccessPoint::Key, std::shared_ptr<GroupedAccessPoint>> grouper; |
437 | bool disabled; |
438 | std::uint32_t lastState; |
439 | std::string name; |
440 | @@ -165,13 +113,23 @@ |
441 | return; |
442 | } |
443 | } |
444 | + |
445 | + platform::nmofono::wifi::AccessPoint::Ptr shap; |
446 | + try { |
447 | + NM::Interface::AccessPoint ap(p->nm.service->object_for_path(path)); |
448 | + shap = std::make_shared<platform::nmofono::wifi::AccessPoint>(ap); |
449 | + } catch(const std::exception &e) { |
450 | + std::cerr << __PRETTY_FUNCTION__ << ": failed to create AccessPoint proxy for "<< path.as_string() << ": " << std::endl |
451 | + << "\t" << e.what() << std::endl |
452 | + << "\tIgnoring." << std::endl; |
453 | + return; |
454 | + } |
455 | + |
456 | auto list = p->rawAccessPoints.get(); |
457 | - NM::Interface::AccessPoint ap(p->nm.service->object_for_path(path)); |
458 | - auto shap = std::make_shared<platform::nmofono::wifi::AccessPoint>(ap); |
459 | list.insert(shap); |
460 | p->rawAccessPoints.set(list); |
461 | |
462 | - auto k = build_key(shap); |
463 | + auto k = AccessPoint::Key(shap); |
464 | if(p->grouper.find(k) != p->grouper.end()) { |
465 | p->grouper[k]->add_ap(shap); |
466 | } else { |
467 | @@ -200,7 +158,7 @@ |
468 | } |
469 | } |
470 | if (!shap) { |
471 | - std::cerr << "Tried to remove access point " << path.as_string() << " that has not been added." << std::endl; |
472 | + std::cerr << __PRETTY_FUNCTION__ << ": Tried to remove access point " << path.as_string() << " that has not been added." << std::endl; |
473 | return; |
474 | } |
475 | p->rawAccessPoints.set(list); |
476 | @@ -345,11 +303,11 @@ |
477 | // The accesspoint interface does not provide this property so we need to coax it out of |
478 | // derived classes. |
479 | if(ap) { |
480 | - ssid = ap->get_ap().ssid->get(); |
481 | + ssid = ap->raw_ssid(); |
482 | } else { |
483 | std::shared_ptr<AccessPoint> bap = std::dynamic_pointer_cast<AccessPoint>(accessPoint); |
484 | assert(bap); |
485 | - ssid = bap->get_ap().ssid->get(); |
486 | + ssid = bap->raw_ssid(); |
487 | } |
488 | NM::Interface::Connection *found = nullptr; |
489 | auto connections = p->dev.get_available_connections(); |
490 | @@ -360,7 +318,7 @@ |
491 | if (conf.first == "ssid") { |
492 | std::vector<int8_t> value; |
493 | value = conf.second.as<std::vector<std::int8_t>>(); |
494 | - if (value == ap->get_ap().ssid->get()) { |
495 | + if (value == ap->raw_ssid()) { |
496 | found = &con; |
497 | break; |
498 | } |
499 | @@ -384,7 +342,7 @@ |
500 | /// @todo getting the ssid multiple times over dbus is stupid. |
501 | |
502 | std::map<std::string, dbus::types::Variant> wireless_conf; |
503 | - wireless_conf["ssid"] = dbus::types::Variant::encode<std::vector<std::int8_t>>(ap->get_ap().ssid->get()); |
504 | + wireless_conf["ssid"] = dbus::types::Variant::encode<std::vector<std::int8_t>>(ap->raw_ssid()); |
505 | |
506 | conf["802-11-wireless"] = wireless_conf; |
507 | auto ret = p->nm.add_and_activate_connection(conf, |
508 | |
509 | === modified file 'src/indicator/CMakeLists.txt' |
510 | --- src/indicator/CMakeLists.txt 2014-08-19 21:03:04 +0000 |
511 | +++ src/indicator/CMakeLists.txt 2014-10-31 14:07:40 +0000 |
512 | @@ -7,19 +7,18 @@ |
513 | service.h |
514 | indicator-menu.h |
515 | modem.cpp |
516 | - modem.h |
517 | modem-manager.cpp |
518 | quick-access-section.cpp |
519 | sim-unlock-dialog.cpp |
520 | root-state.cpp |
521 | - wifi-link-item.h |
522 | + wifi-link-item.cpp |
523 | wifi-section.cpp |
524 | wwan-link-item.cpp |
525 | wwan-section.cpp |
526 | |
527 | connectivity-service/connectivity-service.cpp |
528 | |
529 | - menuitems/access-point-item.h |
530 | + menuitems/access-point-item.cpp |
531 | menuitems/item.h |
532 | menuitems/modem-info-item.cpp |
533 | menuitems/section.h |
534 | |
535 | === modified file 'src/indicator/connectivity-service/connectivity-service.cpp' |
536 | --- src/indicator/connectivity-service/connectivity-service.cpp 2014-09-12 10:51:35 +0000 |
537 | +++ src/indicator/connectivity-service/connectivity-service.cpp 2014-10-31 14:07:40 +0000 |
538 | @@ -20,6 +20,8 @@ |
539 | #include "connectivity-service.h" |
540 | #include <dbus-cpp/services/connectivity.h> |
541 | |
542 | +#include <menumodel-cpp/gio-helpers/util.h> |
543 | + |
544 | #include <core/dbus/asio/executor.h> |
545 | #include <core/dbus/helper/type_mapper.h> |
546 | |
547 | @@ -81,7 +83,7 @@ |
548 | }; |
549 | } |
550 | |
551 | -class ConnectivityService::Private |
552 | +class ConnectivityService::Private : public std::enable_shared_from_this<Private> |
553 | { |
554 | public: |
555 | std::thread m_connectivityServiceWorker; |
556 | @@ -105,6 +107,7 @@ |
557 | |
558 | Private() = delete; |
559 | Private(std::shared_ptr<networking::Manager> manager); |
560 | + void ConstructL(); |
561 | ~Private(); |
562 | |
563 | void updateNetworkingStatus(); |
564 | @@ -114,9 +117,18 @@ |
565 | |
566 | ConnectivityService::Private::Private(std::shared_ptr<networking::Manager> manager) |
567 | : m_manager{manager} |
568 | +{} |
569 | + |
570 | +void |
571 | +ConnectivityService::Private::ConstructL() |
572 | { |
573 | - m_manager->characteristics().changed().connect(std::bind(&Private::updateNetworkingStatus, this)); |
574 | - m_manager->status().changed().connect(std::bind(&Private::updateNetworkingStatus, this)); |
575 | + auto that = shared_from_this(); |
576 | + m_manager->characteristics().changed().connect( |
577 | + [that](int){ GMainLoopDispatch([that](){ that->updateNetworkingStatus(); }); }); |
578 | + |
579 | + typedef connectivity::networking::Manager::NetworkingStatus NetworkingStatus; |
580 | + m_manager->status().changed().connect( |
581 | + [that](NetworkingStatus){ GMainLoopDispatch([that](){ that->updateNetworkingStatus(); }); }); |
582 | |
583 | m_bus = std::make_shared<core::dbus::Bus>(core::dbus::WellKnownBus::session); |
584 | |
585 | @@ -185,7 +197,9 @@ |
586 | { |
587 | auto reply = core::dbus::Message::make_method_return(msg); |
588 | m_bus->send(reply); |
589 | - m_unlockAllModems(); |
590 | + |
591 | + auto that = shared_from_this(); |
592 | + GMainLoopDispatch([that](){ that->m_unlockAllModems(); }); |
593 | }); |
594 | } |
595 | |
596 | @@ -306,7 +320,9 @@ |
597 | |
598 | ConnectivityService::ConnectivityService(std::shared_ptr<networking::Manager> manager) |
599 | : d{new Private(manager)} |
600 | -{} |
601 | +{ |
602 | + d->ConstructL(); |
603 | +} |
604 | |
605 | ConnectivityService::~ConnectivityService() |
606 | {} |
607 | |
608 | === modified file 'src/indicator/connectivity-service/connectivity-service.h' |
609 | --- src/indicator/connectivity-service/connectivity-service.h 2014-08-07 23:00:39 +0000 |
610 | +++ src/indicator/connectivity-service/connectivity-service.h 2014-10-31 14:07:40 +0000 |
611 | @@ -29,11 +29,14 @@ |
612 | ConnectivityService(std::shared_ptr<connectivity::networking::Manager> manager); |
613 | virtual ~ConnectivityService(); |
614 | |
615 | + /** |
616 | + * synced with GMainLoop |
617 | + */ |
618 | core::Signal<> &unlockAllModems(); |
619 | |
620 | private: |
621 | class Private; |
622 | - std::unique_ptr<Private> d; |
623 | + std::shared_ptr<Private> d; |
624 | }; |
625 | |
626 | #endif |
627 | |
628 | === modified file 'src/indicator/indicator-network-service.cpp' |
629 | --- src/indicator/indicator-network-service.cpp 2014-08-15 11:52:50 +0000 |
630 | +++ src/indicator/indicator-network-service.cpp 2014-10-31 14:07:40 +0000 |
631 | @@ -86,6 +86,8 @@ |
632 | |
633 | std::shared_ptr<Service> menu {new Service(manager)}; |
634 | std::unique_ptr<ConnectivityService> connectivityService {new ConnectivityService(manager)}; |
635 | + |
636 | + // unlockAllModems is dispatched from GMainLoop |
637 | connectivityService->unlockAllModems().connect([menu](){ menu->unlockAllModems(); }); |
638 | |
639 | if (getenv("VALGRIND") != 0) { |
640 | |
641 | === renamed file 'src/indicator/menuitems/access-point-item.h' => 'src/indicator/menuitems/access-point-item.cpp' |
642 | --- src/indicator/menuitems/access-point-item.h 2014-08-15 11:49:44 +0000 |
643 | +++ src/indicator/menuitems/access-point-item.cpp 2014-10-31 14:07:40 +0000 |
644 | @@ -17,32 +17,42 @@ |
645 | * Antti Kaijanmäki <antti.kaijanmaki@canonical.com> |
646 | */ |
647 | |
648 | -#ifndef ACCESS_POINT_ITEM_H |
649 | -#define ACCESS_POINT_ITEM_H |
650 | +#include "access-point-item.h" |
651 | |
652 | -#include "item.h" |
653 | #include "menumodel-cpp/action.h" |
654 | #include "menumodel-cpp/menu-item.h" |
655 | #include "menumodel-cpp/gio-helpers/variant.h" |
656 | |
657 | -#include <core/signal.h> |
658 | - |
659 | -#include <connectivity/networking/wifi/access-point.h> |
660 | namespace networking = connectivity::networking; |
661 | |
662 | #include <functional> |
663 | #include <vector> |
664 | |
665 | -class AccessPointItem : public Item |
666 | +class AccessPointItem::Private : public std::enable_shared_from_this<Private> |
667 | { |
668 | - |
669 | public: |
670 | - typedef std::shared_ptr<AccessPointItem> Ptr; |
671 | - |
672 | - AccessPointItem() = delete; |
673 | - explicit AccessPointItem(networking::wifi::AccessPoint::Ptr accessPoint, bool isActive = false) |
674 | - : m_accessPoint{accessPoint}, |
675 | + AccessPointItem *q; |
676 | + |
677 | + networking::wifi::AccessPoint::Ptr m_accessPoint; |
678 | + bool m_isActive; |
679 | + |
680 | + core::Signal<void> m_activated; |
681 | + |
682 | + std::vector<core::Connection> m_connections; |
683 | + |
684 | + Action::Ptr m_actionActivate; |
685 | + Action::Ptr m_actionStrength; |
686 | + MenuItem::Ptr m_item; |
687 | + |
688 | + |
689 | + Private() = delete; |
690 | + explicit Private(AccessPointItem *parent, networking::wifi::AccessPoint::Ptr accessPoint, bool isActive = false) |
691 | + : q{parent}, |
692 | + m_accessPoint{accessPoint}, |
693 | m_isActive{isActive} |
694 | + {} |
695 | + |
696 | + void ConstructL() |
697 | { |
698 | static int id = 0; |
699 | ++id; /// @todo guard me. |
700 | @@ -64,9 +74,17 @@ |
701 | nullptr, |
702 | TypedVariant<std::uint8_t>(m_accessPoint->strength().get())); |
703 | |
704 | - auto con = m_accessPoint->strength().changed().connect(std::bind(&AccessPointItem::setStrength, |
705 | - this, |
706 | - std::placeholders::_1)); |
707 | + auto weak = std::weak_ptr<Private>(shared_from_this()); |
708 | + auto con = m_accessPoint->strength().changed().connect([weak](double value) |
709 | + { |
710 | + auto that = weak.lock(); |
711 | + if (!that) |
712 | + return; |
713 | + GMainLoopDispatch([that, value]() |
714 | + { |
715 | + that->setStrength(value); |
716 | + }); |
717 | + }); |
718 | m_connections.push_back(con); |
719 | |
720 | m_actionActivate = std::make_shared<Action>(actionId, |
721 | @@ -79,11 +97,11 @@ |
722 | m_activated(); |
723 | }); |
724 | |
725 | - m_actionGroup->add(m_actionActivate); |
726 | - m_actionGroup->add(m_actionStrength); |
727 | + q->actionGroup()->add(m_actionActivate); |
728 | + q->actionGroup()->add(m_actionStrength); |
729 | } |
730 | |
731 | - virtual ~AccessPointItem() |
732 | + virtual ~Private() |
733 | { |
734 | for (auto con : m_connections) |
735 | con.disconnect(); |
736 | @@ -94,35 +112,32 @@ |
737 | /// @todo narrow_cast<>; |
738 | m_actionStrength->setState(TypedVariant<std::uint8_t>(value)); |
739 | } |
740 | - |
741 | - void setActive(bool value) |
742 | - { |
743 | - m_isActive = value; |
744 | - m_actionActivate->setState(TypedVariant<bool>(m_isActive)); |
745 | - } |
746 | - |
747 | - virtual MenuItem::Ptr |
748 | - menuItem() |
749 | - { |
750 | - return m_item; |
751 | - } |
752 | - |
753 | - core::Signal<void> &activated() |
754 | - { |
755 | - return m_activated; |
756 | - } |
757 | - |
758 | -private: |
759 | - networking::wifi::AccessPoint::Ptr m_accessPoint; |
760 | - bool m_isActive; |
761 | - |
762 | - core::Signal<void> m_activated; |
763 | - |
764 | - std::vector<core::Connection> m_connections; |
765 | - |
766 | - Action::Ptr m_actionActivate; |
767 | - Action::Ptr m_actionStrength; |
768 | - MenuItem::Ptr m_item; |
769 | }; |
770 | |
771 | -#endif // ACCESS_POINT_ITEM_H |
772 | +AccessPointItem::AccessPointItem(networking::wifi::AccessPoint::Ptr accessPoint, bool isActive) |
773 | + : d{new Private(this, accessPoint, isActive)} |
774 | +{ |
775 | + d->ConstructL(); |
776 | +} |
777 | + |
778 | +AccessPointItem::~AccessPointItem() |
779 | +{} |
780 | + |
781 | +void |
782 | +AccessPointItem::setActive(bool value) |
783 | +{ |
784 | + d->m_isActive = value; |
785 | + d->m_actionActivate->setState(TypedVariant<bool>(d->m_isActive)); |
786 | +} |
787 | + |
788 | +MenuItem::Ptr |
789 | +AccessPointItem::menuItem() |
790 | +{ |
791 | + return d->m_item; |
792 | +} |
793 | + |
794 | +core::Signal<void> & |
795 | +AccessPointItem::activated() |
796 | +{ |
797 | + return d->m_activated; |
798 | +} |
799 | |
800 | === added file 'src/indicator/menuitems/access-point-item.h' |
801 | --- src/indicator/menuitems/access-point-item.h 1970-01-01 00:00:00 +0000 |
802 | +++ src/indicator/menuitems/access-point-item.h 2014-10-31 14:07:40 +0000 |
803 | @@ -0,0 +1,44 @@ |
804 | +/* |
805 | + * Copyright (C) 2014 Canonical, Ltd. |
806 | + * |
807 | + * This program is free software: you can redistribute it and/or modify it |
808 | + * under the terms of the GNU General Public License version 3, as published |
809 | + * by the Free Software Foundation. |
810 | + * |
811 | + * This program is distributed in the hope that it will be useful, but |
812 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
813 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
814 | + * PURPOSE. See the GNU General Public License for more details. |
815 | + * |
816 | + * You should have received a copy of the GNU General Public License along |
817 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
818 | + * |
819 | + * Authors: |
820 | + * Antti Kaijanmäki <antti.kaijanmaki@canonical.com> |
821 | + */ |
822 | + |
823 | +#ifndef ACCESS_POINT_ITEM_H |
824 | +#define ACCESS_POINT_ITEM_H |
825 | + |
826 | +#include <connectivity/networking/wifi/access-point.h> |
827 | +#include "item.h" |
828 | + |
829 | +class AccessPointItem : public Item |
830 | +{ |
831 | + class Private; |
832 | + std::shared_ptr<Private> d; |
833 | + |
834 | +public: |
835 | + typedef std::shared_ptr<AccessPointItem> Ptr; |
836 | + |
837 | + AccessPointItem() = delete; |
838 | + explicit AccessPointItem(connectivity::networking::wifi::AccessPoint::Ptr accessPoint, bool isActive = false); |
839 | + virtual ~AccessPointItem(); |
840 | + |
841 | + void setActive(bool value); |
842 | + |
843 | + virtual MenuItem::Ptr menuItem(); |
844 | + core::Signal<void> &activated(); |
845 | +}; |
846 | + |
847 | +#endif // ACCESS_POINT_ITEM_H |
848 | |
849 | === modified file 'src/indicator/modem-manager.cpp' |
850 | --- src/indicator/modem-manager.cpp 2014-10-15 11:31:13 +0000 |
851 | +++ src/indicator/modem-manager.cpp 2014-10-31 14:07:40 +0000 |
852 | @@ -19,6 +19,8 @@ |
853 | |
854 | #include "modem-manager.h" |
855 | |
856 | +#include <menumodel-cpp/gio-helpers/util.h> |
857 | + |
858 | #include <notify-cpp/snapdecision/sim-unlock.h> |
859 | |
860 | #include "dbus-cpp/services/ofono.h" |
861 | @@ -30,7 +32,7 @@ |
862 | |
863 | #include "sim-unlock-dialog.h" |
864 | |
865 | -class ModemManager::Private |
866 | +class ModemManager::Private : public std::enable_shared_from_this<Private> |
867 | { |
868 | public: |
869 | |
870 | @@ -47,6 +49,10 @@ |
871 | std::list<Modem::Ptr> m_pendingUnlocks; |
872 | |
873 | Private() |
874 | + {} |
875 | + |
876 | + void |
877 | + ConstructL() |
878 | { |
879 | m_bus = std::make_shared<core::dbus::Bus>(core::dbus::WellKnownBus::system); |
880 | |
881 | @@ -83,8 +89,10 @@ |
882 | ofono_disappeared(); |
883 | } |
884 | m_watcher = m_dbus->make_service_watcher(org::ofono::Service::name()); |
885 | - m_watcher->service_registered().connect([this]() { ofono_appeared(); }); |
886 | - m_watcher->service_unregistered().connect([this](){ ofono_disappeared(); }); |
887 | + |
888 | + auto that = shared_from_this(); |
889 | + m_watcher->service_registered().connect([that](){ GMainLoopDispatch([that](){ that->ofono_appeared(); }); }); |
890 | + m_watcher->service_unregistered().connect([that](){ GMainLoopDispatch([that](){ that->ofono_disappeared(); }); }); |
891 | } |
892 | |
893 | ~Private() |
894 | @@ -109,7 +117,10 @@ |
895 | std::cerr << e.what() << std::endl; |
896 | } |
897 | |
898 | - m_ofono->manager->modems.changed().connect(std::bind(&Private::modems_changed, this, std::placeholders::_1)); |
899 | + auto that = shared_from_this(); |
900 | + m_ofono->manager->modems.changed().connect( |
901 | + [that](std::map<core::dbus::types::ObjectPath, org::ofono::Interface::Modem::Ptr> modems) |
902 | + { GMainLoopDispatch([that, modems]() { that->modems_changed(modems); }); }); |
903 | modems_changed(m_ofono->manager->modems.get()); |
904 | } |
905 | |
906 | @@ -171,8 +182,9 @@ |
907 | }; |
908 | |
909 | ModemManager::ModemManager() |
910 | + : d{new Private} |
911 | { |
912 | - d.reset(new Private); |
913 | + d->ConstructL(); |
914 | } |
915 | |
916 | ModemManager::~ModemManager() |
917 | |
918 | === modified file 'src/indicator/modem-manager.h' |
919 | --- src/indicator/modem-manager.h 2014-08-07 20:24:48 +0000 |
920 | +++ src/indicator/modem-manager.h 2014-10-31 14:07:40 +0000 |
921 | @@ -28,7 +28,7 @@ |
922 | class ModemManager |
923 | { |
924 | class Private; |
925 | - std::unique_ptr<Private> d; |
926 | + std::shared_ptr<Private> d; |
927 | |
928 | public: |
929 | |
930 | @@ -37,9 +37,19 @@ |
931 | ModemManager(); |
932 | ~ModemManager(); |
933 | |
934 | + /** |
935 | + * must be called from GMainLoop |
936 | + */ |
937 | void unlockModem(Modem::Ptr modem); |
938 | + |
939 | + /** |
940 | + * must be called from GMainLoop |
941 | + */ |
942 | void unlockAllModems(); |
943 | |
944 | + /** |
945 | + * changed() emitted from GMainLoop |
946 | + */ |
947 | const core::Property<std::set<Modem::Ptr>> &modems(); |
948 | }; |
949 | |
950 | |
951 | === modified file 'src/indicator/modem.cpp' |
952 | --- src/indicator/modem.cpp 2014-10-08 09:45:57 +0000 |
953 | +++ src/indicator/modem.cpp 2014-10-31 14:07:40 +0000 |
954 | @@ -19,7 +19,9 @@ |
955 | |
956 | #include "modem.h" |
957 | |
958 | -class Modem::Private |
959 | +#include <menumodel-cpp/gio-helpers/util.h> |
960 | + |
961 | +class Modem::Private : public std::enable_shared_from_this<Private> |
962 | { |
963 | public: |
964 | core::Property<bool> m_online; |
965 | @@ -41,8 +43,60 @@ |
966 | void simManagerChanged(org::ofono::Interface::SimManager::Ptr simmgr); |
967 | |
968 | void update(); |
969 | + |
970 | + Private() = delete; |
971 | + Private(org::ofono::Interface::Modem::Ptr ofonoModem); |
972 | + void ConstructL(); |
973 | }; |
974 | |
975 | +Modem::Private::Private(org::ofono::Interface::Modem::Ptr ofonoModem) |
976 | + : m_ofonoModem{ofonoModem} |
977 | +{} |
978 | + |
979 | +void |
980 | +Modem::Private::ConstructL() |
981 | +{ |
982 | + auto that = shared_from_this(); |
983 | + |
984 | + m_online.set(m_ofonoModem->online.get()); |
985 | + m_ofonoModem->online.changed().connect([that](bool value){ |
986 | + GMainLoopDispatch([that, value]() { |
987 | + that->m_online.set(value); |
988 | + }); |
989 | + }); |
990 | + |
991 | + simManagerChanged(m_ofonoModem->simManager.get()); |
992 | + m_ofonoModem->simManager.changed().connect([that](org::ofono::Interface::SimManager::Ptr simmgr) |
993 | + { |
994 | + GMainLoopDispatch([that, simmgr](){ |
995 | + that->simManagerChanged(simmgr); |
996 | + }); |
997 | + }); |
998 | + |
999 | + networkRegistrationChanged(m_ofonoModem->networkRegistration.get()); |
1000 | + m_ofonoModem->networkRegistration.changed().connect([that](org::ofono::Interface::NetworkRegistration::Ptr netreg) |
1001 | + { |
1002 | + GMainLoopDispatch([that, netreg](){ |
1003 | + that->networkRegistrationChanged(netreg); |
1004 | + }); |
1005 | + }); |
1006 | + |
1007 | + /// @todo hook up with system-settings to allow changing the identifier. |
1008 | + /// for now just provide the defaults |
1009 | + const auto path = m_ofonoModem->object->path().as_string(); |
1010 | + if (path == "/ril_0") { |
1011 | + m_simIdentifier.set("SIM 1"); |
1012 | + m_index = 1; |
1013 | + } else if (path == "/ril_1") { |
1014 | + m_simIdentifier.set("SIM 2"); |
1015 | + m_index = 2; |
1016 | + } else { |
1017 | + m_simIdentifier.set(path); |
1018 | + } |
1019 | + |
1020 | +} |
1021 | + |
1022 | + |
1023 | void |
1024 | Modem::Private::update() |
1025 | { |
1026 | @@ -119,10 +173,38 @@ |
1027 | Modem::Private::networkRegistrationChanged(org::ofono::Interface::NetworkRegistration::Ptr netreg) |
1028 | { |
1029 | if (netreg) { |
1030 | - netreg->operatorName.changed().connect(std::bind(&Private::update, this)); |
1031 | - netreg->status.changed().connect(std::bind(&Private::update, this)); |
1032 | - netreg->strength.changed().connect(std::bind(&Private::update, this)); |
1033 | - netreg->technology.changed().connect(std::bind(&Private::update, this)); |
1034 | + auto that = shared_from_this(); |
1035 | + netreg->operatorName.changed().connect([that](const std::string &) |
1036 | + { |
1037 | + GMainLoopDispatch([that]() |
1038 | + { |
1039 | + that->update(); |
1040 | + }); |
1041 | + }); |
1042 | + netreg->status.changed().connect([that](org::ofono::Interface::NetworkRegistration::Status) |
1043 | + { |
1044 | + GMainLoopDispatch([that]() |
1045 | + { |
1046 | + that->update(); |
1047 | + }); |
1048 | + }); |
1049 | + |
1050 | + netreg->strength.changed().connect([that](std::int8_t) |
1051 | + { |
1052 | + GMainLoopDispatch([that]() |
1053 | + { |
1054 | + that->update(); |
1055 | + }); |
1056 | + }); |
1057 | + |
1058 | + netreg->technology.changed().connect([that](org::ofono::Interface::NetworkRegistration::Technology) |
1059 | + { |
1060 | + GMainLoopDispatch([that]() |
1061 | + { |
1062 | + that->update(); |
1063 | + }); |
1064 | + }); |
1065 | + |
1066 | } |
1067 | update(); |
1068 | } |
1069 | @@ -132,41 +214,39 @@ |
1070 | Modem::Private::simManagerChanged(org::ofono::Interface::SimManager::Ptr simmgr) |
1071 | { |
1072 | if (simmgr) { |
1073 | - simmgr->present.changed().connect(std::bind(&Private::update, this)); |
1074 | - simmgr->pinRequired.changed().connect(std::bind(&Private::update, this)); |
1075 | - simmgr->retries.changed().connect(std::bind(&Private::update, this)); |
1076 | + auto that = shared_from_this(); |
1077 | + simmgr->present.changed().connect([that](bool) |
1078 | + { |
1079 | + GMainLoopDispatch([that]() |
1080 | + { |
1081 | + that->update(); |
1082 | + }); |
1083 | + }); |
1084 | + |
1085 | + simmgr->pinRequired.changed().connect([that](org::ofono::Interface::SimManager::PinType) |
1086 | + { |
1087 | + GMainLoopDispatch([that]() |
1088 | + { |
1089 | + that->update(); |
1090 | + }); |
1091 | + }); |
1092 | + |
1093 | + simmgr->retries.changed().connect([that](std::map<org::ofono::Interface::SimManager::PinType, std::uint8_t>) |
1094 | + { |
1095 | + GMainLoopDispatch([that]() |
1096 | + { |
1097 | + that->update(); |
1098 | + }); |
1099 | + }); |
1100 | + |
1101 | } |
1102 | update(); |
1103 | } |
1104 | |
1105 | Modem::Modem(org::ofono::Interface::Modem::Ptr ofonoModem) |
1106 | + : d{new Private(ofonoModem)} |
1107 | { |
1108 | - d.reset(new Private); |
1109 | - d->m_ofonoModem = ofonoModem; |
1110 | - |
1111 | - d->m_online.set(d->m_ofonoModem->online.get()); |
1112 | - d->m_ofonoModem->online.changed().connect([this](bool value){ |
1113 | - d->m_online.set(value); |
1114 | - }); |
1115 | - |
1116 | - d->simManagerChanged(d->m_ofonoModem->simManager.get()); |
1117 | - d->m_ofonoModem->simManager.changed().connect(std::bind(&Private::simManagerChanged, d.get(), std::placeholders::_1)); |
1118 | - |
1119 | - d->networkRegistrationChanged(d->m_ofonoModem->networkRegistration.get()); |
1120 | - d->m_ofonoModem->networkRegistration.changed().connect(std::bind(&Private::networkRegistrationChanged, d.get(), std::placeholders::_1)); |
1121 | - |
1122 | - /// @todo hook up with system-settings to allow changing the identifier. |
1123 | - /// for now just provide the defaults |
1124 | - const auto path = ofonoModem->object->path().as_string(); |
1125 | - if (path == "/ril_0") { |
1126 | - d->m_simIdentifier.set("SIM 1"); |
1127 | - d->m_index = 1; |
1128 | - } else if (path == "/ril_1") { |
1129 | - d->m_simIdentifier.set("SIM 2"); |
1130 | - d->m_index = 2; |
1131 | - } else { |
1132 | - d->m_simIdentifier.set(path); |
1133 | - } |
1134 | + d->ConstructL(); |
1135 | } |
1136 | |
1137 | Modem::~Modem() |
1138 | |
1139 | === modified file 'src/indicator/modem.h' |
1140 | --- src/indicator/modem.h 2014-10-02 11:36:00 +0000 |
1141 | +++ src/indicator/modem.h 2014-10-31 14:07:40 +0000 |
1142 | @@ -27,10 +27,13 @@ |
1143 | |
1144 | #include "dbus-cpp/services/ofono.h" |
1145 | |
1146 | +/** |
1147 | + * all signals and property changes emitted from GMainLoop |
1148 | + */ |
1149 | class Modem |
1150 | { |
1151 | class Private; |
1152 | - std::unique_ptr<Private> d; |
1153 | + std::shared_ptr<Private> d; |
1154 | |
1155 | public: |
1156 | enum class PinType |
1157 | |
1158 | === modified file 'src/indicator/quick-access-section.cpp' |
1159 | --- src/indicator/quick-access-section.cpp 2014-10-09 10:58:30 +0000 |
1160 | +++ src/indicator/quick-access-section.cpp 2014-10-31 14:07:40 +0000 |
1161 | @@ -26,7 +26,7 @@ |
1162 | |
1163 | namespace networking = connectivity::networking; |
1164 | |
1165 | -class QuickAccessSection::Private |
1166 | +class QuickAccessSection::Private : public std::enable_shared_from_this<Private> |
1167 | { |
1168 | public: |
1169 | ActionGroupMerger::Ptr m_actionGroupMerger; |
1170 | @@ -36,15 +36,23 @@ |
1171 | |
1172 | SwitchItem::Ptr m_flightModeSwitch; |
1173 | |
1174 | + Private() = delete; |
1175 | Private(std::shared_ptr<networking::Manager> manager); |
1176 | + void ConstructL(); |
1177 | }; |
1178 | |
1179 | QuickAccessSection::Private::Private(std::shared_ptr<networking::Manager> manager) |
1180 | : m_manager{manager} |
1181 | +{} |
1182 | + |
1183 | +void |
1184 | +QuickAccessSection::Private::ConstructL() |
1185 | { |
1186 | m_actionGroupMerger = std::make_shared<ActionGroupMerger>(); |
1187 | m_menu = std::make_shared<Menu>(); |
1188 | |
1189 | + auto that = shared_from_this(); |
1190 | + |
1191 | m_flightModeSwitch = std::make_shared<SwitchItem>(_("Flight Mode"), "airplane", "enabled"); |
1192 | switch (m_manager->flightMode().get()) { |
1193 | case networking::Manager::FlightModeStatus::off: |
1194 | @@ -54,15 +62,18 @@ |
1195 | m_flightModeSwitch->state().set(true); |
1196 | break; |
1197 | } |
1198 | - m_manager->flightMode().changed().connect([this](networking::Manager::FlightModeStatus value){ |
1199 | - switch (value) { |
1200 | - case networking::Manager::FlightModeStatus::off: |
1201 | - m_flightModeSwitch->state().set(false); |
1202 | - break; |
1203 | - case networking::Manager::FlightModeStatus::on: |
1204 | - m_flightModeSwitch->state().set(true); |
1205 | - break; |
1206 | - } |
1207 | + m_manager->flightMode().changed().connect([that](networking::Manager::FlightModeStatus value){ |
1208 | + GMainLoopDispatch([that, value] |
1209 | + { |
1210 | + switch (value) { |
1211 | + case networking::Manager::FlightModeStatus::off: |
1212 | + that->m_flightModeSwitch->state().set(false); |
1213 | + break; |
1214 | + case networking::Manager::FlightModeStatus::on: |
1215 | + that->m_flightModeSwitch->state().set(true); |
1216 | + break; |
1217 | + } |
1218 | + }); |
1219 | }); |
1220 | m_flightModeSwitch->activated().connect([this](){ |
1221 | if (m_flightModeSwitch->state().get()) { |
1222 | @@ -85,8 +96,9 @@ |
1223 | } |
1224 | |
1225 | QuickAccessSection::QuickAccessSection(std::shared_ptr<networking::Manager> manager) |
1226 | + : d{new Private(manager)} |
1227 | { |
1228 | - d.reset(new Private(manager)); |
1229 | + d->ConstructL(); |
1230 | } |
1231 | |
1232 | QuickAccessSection::~QuickAccessSection() |
1233 | |
1234 | === modified file 'src/indicator/quick-access-section.h' |
1235 | --- src/indicator/quick-access-section.h 2014-04-23 14:41:46 +0000 |
1236 | +++ src/indicator/quick-access-section.h 2014-10-31 14:07:40 +0000 |
1237 | @@ -23,10 +23,13 @@ |
1238 | #include "menuitems/section.h" |
1239 | #include <connectivity/networking/manager.h> |
1240 | |
1241 | +/** |
1242 | + * all signals and property changes emitted from GMainLoop |
1243 | + */ |
1244 | class QuickAccessSection : public Section |
1245 | { |
1246 | class Private; |
1247 | - std::unique_ptr<Private> d; |
1248 | + std::shared_ptr<Private> d; |
1249 | |
1250 | public: |
1251 | typedef std::shared_ptr<QuickAccessSection> Ptr; |
1252 | |
1253 | === modified file 'src/indicator/root-state.cpp' |
1254 | --- src/indicator/root-state.cpp 2014-10-06 08:30:34 +0000 |
1255 | +++ src/indicator/root-state.cpp 2014-10-31 14:07:40 +0000 |
1256 | @@ -24,9 +24,11 @@ |
1257 | #include <connectivity/networking/wifi/link.h> |
1258 | #include <connectivity/networking/wifi/access-point.h> |
1259 | |
1260 | +#include <menumodel-cpp/gio-helpers/util.h> |
1261 | + |
1262 | namespace networking = connectivity::networking; |
1263 | |
1264 | -class RootState::Private |
1265 | +class RootState::Private : public std::enable_shared_from_this<Private> |
1266 | { |
1267 | public: |
1268 | std::shared_ptr<networking::Manager> m_manager; |
1269 | @@ -43,6 +45,7 @@ |
1270 | |
1271 | Private() = delete; |
1272 | Private(std::shared_ptr<networking::Manager> manager, ModemManager::Ptr modemManager); |
1273 | + void ConstructL(); |
1274 | |
1275 | void modemsChanged(const std::set<Modem::Ptr> &modems); |
1276 | |
1277 | @@ -57,14 +60,38 @@ |
1278 | RootState::Private::Private(std::shared_ptr<networking::Manager> manager, ModemManager::Ptr modemManager) |
1279 | : m_manager{manager}, |
1280 | m_modemManager{modemManager} |
1281 | -{ |
1282 | - m_manager->flightMode().changed().connect(std::bind(&Private::updateRootState, this)); |
1283 | - |
1284 | +{} |
1285 | + |
1286 | +void |
1287 | +RootState::Private::ConstructL() |
1288 | +{ |
1289 | + auto that = shared_from_this(); |
1290 | + |
1291 | + m_manager->flightMode().changed().connect([that](connectivity::networking::Manager::FlightModeStatus) |
1292 | + { |
1293 | + GMainLoopDispatch([that](){ |
1294 | + that->updateRootState(); |
1295 | + }); |
1296 | + }); |
1297 | + |
1298 | + modemsChanged(m_modemManager->modems().get()); |
1299 | + // modem properties and signals already synced with GMainLoop |
1300 | m_modemManager->modems().changed().connect(std::bind(&Private::modemsChanged, this, std::placeholders::_1)); |
1301 | - modemsChanged(m_modemManager->modems().get()); |
1302 | - |
1303 | - m_manager->status().changed().connect(std::bind(&Private::updateNetworkingIcon, this)); |
1304 | - m_manager->links().changed().connect(std::bind(&Private::updateNetworkingIcon, this)); |
1305 | + |
1306 | + m_manager->status().changed().connect([that](connectivity::networking::Manager::NetworkingStatus) |
1307 | + { |
1308 | + GMainLoopDispatch([that](){ |
1309 | + that->updateNetworkingIcon(); |
1310 | + }); |
1311 | + }); |
1312 | + |
1313 | + m_manager->links().changed().connect([that](std::set<connectivity::networking::Link::Ptr>) |
1314 | + { |
1315 | + GMainLoopDispatch([that](){ |
1316 | + that->updateNetworkingIcon(); |
1317 | + }); |
1318 | + }); |
1319 | + |
1320 | |
1321 | // will also call updateRootState() |
1322 | updateNetworkingIcon(); |
1323 | @@ -90,6 +117,7 @@ |
1324 | m_cellularIcons.erase(modem); |
1325 | |
1326 | for (auto modem : added) { |
1327 | + // modem properties and signals already synced with GMainLoop |
1328 | modem->online().changed().connect(std::bind(&Private::updateModem, this, Modem::WeakPtr(modem))); |
1329 | modem->simStatus().changed().connect(std::bind(&Private::updateModem, this, Modem::WeakPtr(modem))); |
1330 | modem->status().changed().connect(std::bind(&Private::updateModem, this, Modem::WeakPtr(modem))); |
1331 | @@ -319,8 +347,9 @@ |
1332 | } |
1333 | |
1334 | RootState::RootState(std::shared_ptr<connectivity::networking::Manager> manager, ModemManager::Ptr modemManager) |
1335 | + : d{new Private(manager, modemManager)} |
1336 | { |
1337 | - d.reset(new Private(manager, modemManager)); |
1338 | + d->ConstructL(); |
1339 | } |
1340 | |
1341 | RootState::~RootState() |
1342 | |
1343 | === modified file 'src/indicator/root-state.h' |
1344 | --- src/indicator/root-state.h 2014-05-12 11:36:59 +0000 |
1345 | +++ src/indicator/root-state.h 2014-10-31 14:07:40 +0000 |
1346 | @@ -25,10 +25,13 @@ |
1347 | |
1348 | #include "menumodel-cpp/gio-helpers/variant.h" |
1349 | |
1350 | +/** |
1351 | + * all signals and property changes emitted from GMainLoop |
1352 | + */ |
1353 | class RootState |
1354 | { |
1355 | class Private; |
1356 | - std::unique_ptr<Private> d; |
1357 | + std::shared_ptr<Private> d; |
1358 | |
1359 | public: |
1360 | typedef std::shared_ptr<RootState> Ptr; |
1361 | |
1362 | === modified file 'src/indicator/sim-unlock-dialog.h' |
1363 | --- src/indicator/sim-unlock-dialog.h 2014-10-14 19:54:51 +0000 |
1364 | +++ src/indicator/sim-unlock-dialog.h 2014-10-31 14:07:40 +0000 |
1365 | @@ -23,6 +23,9 @@ |
1366 | #include <memory> |
1367 | #include "modem.h" |
1368 | |
1369 | +/** |
1370 | + * all signals and property changes dispatched from GMainLoop |
1371 | + */ |
1372 | class SimUnlockDialog |
1373 | { |
1374 | class Private; |
1375 | |
1376 | === renamed file 'src/indicator/wifi-link-item.h' => 'src/indicator/wifi-link-item.cpp' |
1377 | --- src/indicator/wifi-link-item.h 2014-09-24 23:37:18 +0000 |
1378 | +++ src/indicator/wifi-link-item.cpp 2014-10-31 14:07:40 +0000 |
1379 | @@ -17,26 +17,26 @@ |
1380 | * Antti Kaijanmäki <antti.kaijanmaki@canonical.com> |
1381 | */ |
1382 | |
1383 | -#ifndef WIFI_LINK_ITEM_H |
1384 | -#define WIFI_LINK_ITEM_H |
1385 | +#include "wifi-link-item.h" |
1386 | |
1387 | -#include "menuitems/switch-item.h" |
1388 | +#include "menuitems/text-item.h" |
1389 | #include "menuitems/access-point-item.h" |
1390 | -#include "menuitems/text-item.h" |
1391 | |
1392 | #include "menumodel-cpp/action-group.h" |
1393 | #include "menumodel-cpp/action-group-merger.h" |
1394 | #include "menumodel-cpp/menu.h" |
1395 | #include "menumodel-cpp/menu-merger.h" |
1396 | |
1397 | -#include <connectivity/networking/wifi/link.h> |
1398 | namespace networking = connectivity::networking; |
1399 | |
1400 | #include <algorithm> |
1401 | #include <locale> |
1402 | |
1403 | -class WifiLinkItem : public Item |
1404 | +class WifiLinkItem::Private : public std::enable_shared_from_this<Private> |
1405 | { |
1406 | +public: |
1407 | + ActionGroupMerger::Ptr m_actionGroupMerger; |
1408 | + |
1409 | networking::wifi::Link::Ptr m_link; |
1410 | |
1411 | /// @todo do something with me... |
1412 | @@ -66,13 +66,18 @@ |
1413 | std::mutex m_updateActiveAccessPointMutex; |
1414 | |
1415 | public: |
1416 | - typedef std::shared_ptr<WifiLinkItem> Ptr; |
1417 | - |
1418 | - WifiLinkItem() = delete; |
1419 | - virtual ~WifiLinkItem() = default; |
1420 | - WifiLinkItem(networking::wifi::Link::Ptr link) |
1421 | + |
1422 | + |
1423 | + Private() = delete; |
1424 | + ~Private() {} |
1425 | + Private(networking::wifi::Link::Ptr link) |
1426 | : m_link {link} |
1427 | + {} |
1428 | + |
1429 | + void ConstructL() |
1430 | { |
1431 | + m_actionGroupMerger = std::make_shared<ActionGroupMerger>(); |
1432 | + |
1433 | m_topMenu = std::make_shared<Menu>(); |
1434 | |
1435 | m_connectedBeforeApsMenu = std::make_shared<Menu>(); |
1436 | @@ -103,14 +108,24 @@ |
1437 | return a_upper < b_upper; |
1438 | }; |
1439 | |
1440 | + auto that = shared_from_this(); |
1441 | + |
1442 | updateAccessPoints(m_link->accessPoints().get()); |
1443 | - m_link->accessPoints().changed().connect([this](std::set<networking::wifi::AccessPoint::Ptr> accessPoints){ |
1444 | - updateAccessPoints(accessPoints); |
1445 | + m_link->accessPoints().changed().connect([that](std::set<networking::wifi::AccessPoint::Ptr> accessPoints) |
1446 | + { |
1447 | + GMainLoopDispatch([that, accessPoints]() |
1448 | + { |
1449 | + that->updateAccessPoints(accessPoints); |
1450 | + }); |
1451 | }); |
1452 | |
1453 | updateActiveAccessPoint(m_link->activeAccessPoint().get()); |
1454 | - m_link->activeAccessPoint().changed().connect([this](networking::wifi::AccessPoint::Ptr ap){ |
1455 | - updateActiveAccessPoint(ap); |
1456 | + m_link->activeAccessPoint().changed().connect([that](networking::wifi::AccessPoint::Ptr ap) |
1457 | + { |
1458 | + GMainLoopDispatch([that, ap]() |
1459 | + { |
1460 | + that->updateActiveAccessPoint(ap); |
1461 | + }); |
1462 | }); |
1463 | |
1464 | m_otherNetwork = std::make_shared<TextItem>(_("Other network…"), "wifi", "othernetwork"); |
1465 | @@ -204,12 +219,26 @@ |
1466 | } |
1467 | } |
1468 | |
1469 | - virtual MenuItem::Ptr |
1470 | - menuItem() { |
1471 | - return m_item; |
1472 | - } |
1473 | - |
1474 | - |
1475 | }; |
1476 | |
1477 | -#endif // WIFI_LINK_ITEM_H |
1478 | + |
1479 | +WifiLinkItem::WifiLinkItem(connectivity::networking::wifi::Link::Ptr link) |
1480 | + : d{new Private(link)} |
1481 | +{ |
1482 | + d->ConstructL(); |
1483 | +} |
1484 | + |
1485 | +WifiLinkItem::~WifiLinkItem() |
1486 | +{} |
1487 | + |
1488 | +ActionGroup::Ptr |
1489 | +WifiLinkItem::actionGroup() |
1490 | +{ |
1491 | + return d->m_actionGroupMerger->actionGroup(); |
1492 | +} |
1493 | + |
1494 | +MenuItem::Ptr |
1495 | +WifiLinkItem::menuItem() |
1496 | +{ |
1497 | + return d->m_item; |
1498 | +} |
1499 | |
1500 | === added file 'src/indicator/wifi-link-item.h' |
1501 | --- src/indicator/wifi-link-item.h 1970-01-01 00:00:00 +0000 |
1502 | +++ src/indicator/wifi-link-item.h 2014-10-31 14:07:40 +0000 |
1503 | @@ -0,0 +1,43 @@ |
1504 | +/* |
1505 | + * Copyright (C) 2014 Canonical, Ltd. |
1506 | + * |
1507 | + * This program is free software: you can redistribute it and/or modify it |
1508 | + * under the terms of the GNU General Public License version 3, as published |
1509 | + * by the Free Software Foundation. |
1510 | + * |
1511 | + * This program is distributed in the hope that it will be useful, but |
1512 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
1513 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
1514 | + * PURPOSE. See the GNU General Public License for more details. |
1515 | + * |
1516 | + * You should have received a copy of the GNU General Public License along |
1517 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
1518 | + * |
1519 | + * Authors: |
1520 | + * Antti Kaijanmäki <antti.kaijanmaki@canonical.com> |
1521 | + */ |
1522 | + |
1523 | +#ifndef WIFI_LINK_ITEM_H |
1524 | +#define WIFI_LINK_ITEM_H |
1525 | + |
1526 | +#include <connectivity/networking/wifi/link.h> |
1527 | + |
1528 | +#include "menuitems/item.h" |
1529 | + |
1530 | +class WifiLinkItem : public Item |
1531 | +{ |
1532 | + class Private; |
1533 | + std::shared_ptr<Private> d; |
1534 | + |
1535 | +public: |
1536 | + typedef std::shared_ptr<WifiLinkItem> Ptr; |
1537 | + |
1538 | + WifiLinkItem() = delete; |
1539 | + WifiLinkItem(connectivity::networking::wifi::Link::Ptr link); |
1540 | + virtual ~WifiLinkItem(); |
1541 | + |
1542 | + virtual MenuItem::Ptr menuItem(); |
1543 | + virtual ActionGroup::Ptr actionGroup(); |
1544 | +}; |
1545 | + |
1546 | +#endif // WIFI_LINK_ITEM_H |
1547 | |
1548 | === modified file 'src/indicator/wifi-section.cpp' |
1549 | --- src/indicator/wifi-section.cpp 2014-09-25 18:48:39 +0000 |
1550 | +++ src/indicator/wifi-section.cpp 2014-10-31 14:07:40 +0000 |
1551 | @@ -23,7 +23,17 @@ |
1552 | |
1553 | #include "url-dispatcher-cpp/url-dispatcher.h" |
1554 | |
1555 | -class WifiSection::Private |
1556 | +#include "menuitems/switch-item.h" |
1557 | +#include "menuitems/text-item.h" |
1558 | + |
1559 | +#include "menumodel-cpp/action-group.h" |
1560 | +#include "menumodel-cpp/action-group-merger.h" |
1561 | +#include "menumodel-cpp/menu.h" |
1562 | +#include "menumodel-cpp/menu-merger.h" |
1563 | + |
1564 | +using namespace connectivity; |
1565 | + |
1566 | +class WifiSection::Private : public std::enable_shared_from_this<Private> |
1567 | { |
1568 | public: |
1569 | std::shared_ptr<connectivity::networking::Manager> m_manager; |
1570 | @@ -40,6 +50,10 @@ |
1571 | Private() = delete; |
1572 | Private(std::shared_ptr<connectivity::networking::Manager> manager) |
1573 | : m_manager{manager} |
1574 | + {} |
1575 | + |
1576 | + void |
1577 | + ConstructL() |
1578 | { |
1579 | m_actionGroupMerger = std::make_shared<ActionGroupMerger>(); |
1580 | m_menu = std::make_shared<Menu>(); |
1581 | @@ -56,9 +70,14 @@ |
1582 | m_settingsMenu->append(*m_switch); |
1583 | } |
1584 | |
1585 | + auto that = shared_from_this(); |
1586 | + |
1587 | m_switch->state().set(m_manager->wifiEnabled().get()); |
1588 | - m_manager->wifiEnabled().changed().connect([this](bool value) { |
1589 | - m_switch->state().set(value); |
1590 | + m_manager->wifiEnabled().changed().connect([that](bool value) { |
1591 | + GMainLoopDispatch([that, value]() |
1592 | + { |
1593 | + that->m_switch->state().set(value); |
1594 | + }); |
1595 | }); |
1596 | m_switch->activated().connect([this](){ |
1597 | if (m_switch->state().get()) { |
1598 | @@ -73,8 +92,14 @@ |
1599 | }); |
1600 | |
1601 | |
1602 | - m_manager->links().changed().connect(std::bind(&Private::updateLinks, this)); |
1603 | updateLinks(); |
1604 | + m_manager->links().changed().connect([that](std::set<networking::Link::Ptr>) |
1605 | + { |
1606 | + GMainLoopDispatch([that]() |
1607 | + { |
1608 | + that->updateLinks(); |
1609 | + }); |
1610 | + }); |
1611 | |
1612 | m_openWifiSettings = std::make_shared<TextItem>(_("Wi-Fi settings…"), "wifi", "settings"); |
1613 | m_openWifiSettings->activated().connect([](){ |
1614 | @@ -115,14 +140,13 @@ |
1615 | }; |
1616 | |
1617 | WifiSection::WifiSection(std::shared_ptr<connectivity::networking::Manager> manager) |
1618 | + : d{new Private(manager)} |
1619 | { |
1620 | - d.reset(new Private(manager)); |
1621 | + d->ConstructL(); |
1622 | } |
1623 | |
1624 | WifiSection::~WifiSection() |
1625 | -{ |
1626 | - |
1627 | -} |
1628 | +{} |
1629 | |
1630 | ActionGroup::Ptr |
1631 | WifiSection::actionGroup() |
1632 | |
1633 | === modified file 'src/indicator/wifi-section.h' |
1634 | --- src/indicator/wifi-section.h 2014-08-15 11:49:44 +0000 |
1635 | +++ src/indicator/wifi-section.h 2014-10-31 14:07:40 +0000 |
1636 | @@ -27,7 +27,7 @@ |
1637 | class WifiSection : public Section |
1638 | { |
1639 | class Private; |
1640 | - std::unique_ptr<Private> d; |
1641 | + std::shared_ptr<Private> d; |
1642 | |
1643 | public: |
1644 | typedef std::shared_ptr<WifiSection> Ptr; |
1645 | |
1646 | === modified file 'src/indicator/wwan-link-item.cpp' |
1647 | --- src/indicator/wwan-link-item.cpp 2014-10-02 11:36:00 +0000 |
1648 | +++ src/indicator/wwan-link-item.cpp 2014-10-31 14:07:40 +0000 |
1649 | @@ -23,7 +23,7 @@ |
1650 | |
1651 | #include "menumodel-cpp/menu.h" |
1652 | |
1653 | -class WwanLinkItem::Private |
1654 | +class WwanLinkItem::Private : public std::enable_shared_from_this<Private> |
1655 | { |
1656 | public: |
1657 | |
1658 | @@ -39,6 +39,7 @@ |
1659 | |
1660 | Private() = delete; |
1661 | Private(Modem::Ptr modem, ModemManager::Ptr modemManager); |
1662 | + void ConstructL(); |
1663 | |
1664 | void update(); |
1665 | void unlockSim(); |
1666 | @@ -47,6 +48,10 @@ |
1667 | WwanLinkItem::Private::Private(Modem::Ptr modem, ModemManager::Ptr modemManager) |
1668 | : m_modem{modem}, |
1669 | m_modemManager{modemManager} |
1670 | +{} |
1671 | + |
1672 | +void |
1673 | +WwanLinkItem::Private::ConstructL() |
1674 | { |
1675 | m_actionGroupMerger = std::make_shared<ActionGroupMerger>(); |
1676 | m_menu = std::make_shared<Menu>(); |
1677 | @@ -60,6 +65,7 @@ |
1678 | m_showIdentifier.set(false); |
1679 | m_showIdentifier.changed().connect(std::bind(&Private::update, this)); |
1680 | |
1681 | + // already synced with GMainLoop |
1682 | m_modem->online().changed().connect(std::bind(&Private::update, this)); |
1683 | m_modem->simStatus().changed().connect(std::bind(&Private::update, this)); |
1684 | m_modem->operatorName().changed().connect(std::bind(&Private::update, this)); |
1685 | @@ -152,8 +158,10 @@ |
1686 | } |
1687 | |
1688 | WwanLinkItem::WwanLinkItem(Modem::Ptr modem, ModemManager::Ptr modemManager) |
1689 | + : d{new Private(modem, modemManager)} |
1690 | + |
1691 | { |
1692 | - d.reset(new Private(modem, modemManager)); |
1693 | + d->ConstructL(); |
1694 | } |
1695 | |
1696 | WwanLinkItem::~WwanLinkItem() |
1697 | |
1698 | === modified file 'src/indicator/wwan-section.cpp' |
1699 | --- src/indicator/wwan-section.cpp 2014-08-15 10:47:02 +0000 |
1700 | +++ src/indicator/wwan-section.cpp 2014-10-31 14:07:40 +0000 |
1701 | @@ -53,12 +53,17 @@ |
1702 | |
1703 | Private() = delete; |
1704 | Private(ModemManager::Ptr modemManager); |
1705 | + void ConstructL(); |
1706 | |
1707 | void modemsChanged(const std::set<Modem::Ptr> &modems); |
1708 | }; |
1709 | |
1710 | WwanSection::Private::Private(ModemManager::Ptr modemManager) |
1711 | : m_modemManager{modemManager} |
1712 | +{} |
1713 | + |
1714 | +void |
1715 | +WwanSection::Private::ConstructL() |
1716 | { |
1717 | m_actionGroupMerger = std::make_shared<ActionGroupMerger>(); |
1718 | m_menuMerger = std::make_shared<MenuMerger>(); |
1719 | @@ -85,6 +90,7 @@ |
1720 | }); |
1721 | m_actionGroupMerger->add(*m_openCellularSettings); |
1722 | |
1723 | + // already synced with GMainLoop |
1724 | m_modemManager->modems().changed().connect(std::bind(&Private::modemsChanged, this, std::placeholders::_1)); |
1725 | modemsChanged(m_modemManager->modems()); |
1726 | } |
1727 | @@ -149,8 +155,9 @@ |
1728 | } |
1729 | |
1730 | WwanSection::WwanSection(ModemManager::Ptr modemManager) |
1731 | + : d{new Private(modemManager)} |
1732 | { |
1733 | - d.reset(new Private(modemManager)); |
1734 | + d->ConstructL(); |
1735 | } |
1736 | |
1737 | WwanSection::~WwanSection() |
1738 | |
1739 | === modified file 'src/indicator/wwan-section.h' |
1740 | --- src/indicator/wwan-section.h 2014-08-15 11:52:50 +0000 |
1741 | +++ src/indicator/wwan-section.h 2014-10-31 14:07:40 +0000 |
1742 | @@ -26,7 +26,7 @@ |
1743 | class WwanSection : public Section |
1744 | { |
1745 | class Private; |
1746 | - std::unique_ptr<Private> d; |
1747 | + std::shared_ptr<Private> d; |
1748 | |
1749 | public: |
1750 | typedef std::shared_ptr<WwanSection> Ptr; |
1751 | |
1752 | === modified file 'src/menumodel-cpp/gio-helpers/util.cpp' |
1753 | --- src/menumodel-cpp/gio-helpers/util.cpp 2014-09-26 13:07:27 +0000 |
1754 | +++ src/menumodel-cpp/gio-helpers/util.cpp 2014-10-31 14:07:40 +0000 |
1755 | @@ -25,28 +25,28 @@ |
1756 | gboolean |
1757 | GMainLoopDispatch::dispatch_cb(gpointer) |
1758 | { |
1759 | - std::lock_guard<std::mutex> lock(_lock); |
1760 | + std::unique_lock<std::mutex> lock(_lock); |
1761 | for (auto func : _funcs) { |
1762 | + lock.unlock(); |
1763 | (*func)(); |
1764 | + lock.lock(); |
1765 | delete func; |
1766 | } |
1767 | _funcs.clear(); |
1768 | return G_SOURCE_REMOVE; |
1769 | } |
1770 | |
1771 | -GMainLoopDispatch::GMainLoopDispatch(std::function<void()> func) |
1772 | +GMainLoopDispatch::GMainLoopDispatch(Func func) |
1773 | { |
1774 | + std::unique_lock<std::mutex> lock(_lock); |
1775 | + |
1776 | if (g_main_context_acquire(g_main_context_default())) { |
1777 | - if (_funcs.empty()) |
1778 | - func(); |
1779 | - else { |
1780 | - std::function<void()> *funcPtr = new std::function<void()>(func); |
1781 | - _funcs.push_back(funcPtr); |
1782 | - } |
1783 | + // already running inside GMainLoop.. |
1784 | + // free the lock and dispatch immediately. |
1785 | + lock.unlock(); |
1786 | + func(); |
1787 | g_main_context_release(g_main_context_default()); |
1788 | } else { |
1789 | - std::lock_guard<std::mutex> lock(_lock); |
1790 | - |
1791 | std::function<void()> *funcPtr = new std::function<void()>(func); |
1792 | if (_funcs.empty()) { |
1793 | g_idle_add_full(G_PRIORITY_HIGH, |
1794 | |
1795 | === modified file 'src/menumodel-cpp/gio-helpers/util.h' |
1796 | --- src/menumodel-cpp/gio-helpers/util.h 2014-09-26 13:07:27 +0000 |
1797 | +++ src/menumodel-cpp/gio-helpers/util.h 2014-10-31 14:07:40 +0000 |
1798 | @@ -54,7 +54,7 @@ |
1799 | g_main_context_release(g_main_context_default()); |
1800 | } else { |
1801 | std::unique_lock<std::mutex> lk(m_mutex); |
1802 | - g_idle_add_full(G_PRIORITY_HIGH, |
1803 | + g_idle_add_full(G_PRIORITY_HIGH + 1, |
1804 | GSourceFunc(GMainLoopSync::dispatch_cb), |
1805 | this, |
1806 | nullptr); |
1807 | @@ -77,7 +77,7 @@ |
1808 | static std::list<Func *> _funcs; |
1809 | |
1810 | //GMainLoopDispatch() = delete; |
1811 | - GMainLoopDispatch(std::function<void()> func); |
1812 | + GMainLoopDispatch(Func func); |
1813 | }; |
1814 | |
1815 | struct GObjectDeleter { |
1816 | |
1817 | === modified file 'tests/unit/indicator/menuitems/CMakeLists.txt' |
1818 | --- tests/unit/indicator/menuitems/CMakeLists.txt 2014-08-19 21:03:04 +0000 |
1819 | +++ tests/unit/indicator/menuitems/CMakeLists.txt 2014-10-31 14:07:40 +0000 |
1820 | @@ -2,6 +2,7 @@ |
1821 | set( |
1822 | MENUITEMS_CPP_UNIT_TESTS_SRC |
1823 | test-access-point-item.cpp |
1824 | + ${CMAKE_SOURCE_DIR}/src/indicator/menuitems/access-point-item.cpp |
1825 | test-switch-item.cpp |
1826 | ) |
1827 | |
1828 | |
1829 | === modified file 'tests/unit/indicator/menuitems/test-access-point-item.cpp' |
1830 | --- tests/unit/indicator/menuitems/test-access-point-item.cpp 2014-05-12 11:48:42 +0000 |
1831 | +++ tests/unit/indicator/menuitems/test-access-point-item.cpp 2014-10-31 14:07:40 +0000 |
1832 | @@ -30,6 +30,8 @@ |
1833 | using namespace QtDBusTest; |
1834 | using namespace testutils; |
1835 | |
1836 | +using namespace connectivity; |
1837 | + |
1838 | namespace |
1839 | { |
1840 |
I have mixed feelings about this patch.
The "big picture" is this is a step in the right direction and my vote is to approve. I don't like the technical debt being accrued here, but it's preferable to blocking Criticals on an even larger megapatch.
First, The "shared pimpl" idiom of thread safety here is interesting. It's generic enough that it can be (and is) applied liberally here, so that's useful. TBH though, it doesn't make sense to keep processing these signals after the outer object's been destroyed and I would have preferred another solution, e.g. GMainLoopDispatch's destructor calling g_signal_remove() after checking a lock guard to confirm that the func wasn't being called at the same time.
Second, the new comments sprinkled through the code "this must be called from GMainLoop", "these signals are already synced in main loop" etc. are red flags. There are a lot of them and they're hard to test... if there's no code making incorrect calls now (and how would we know for certian?) there surely will be in the future. I'd rather see either (a) a compile-time test of some kind, although I don't know how that would work, or (b) consistent thread rules applied through the code so that everyone knows what the rules of the road are.
Third, many of the ScopedConnections created by connect() are dropped on the floor. Since these connections' lambdas hold handles to the pimpl shared_ptrs, we need to be more careful about disconnecting them when the public objects are destroyed. My concern is that we don't wind up with ghost object chains that continue to process each other's signals.
Lastly (and superficially), I'd also like to see GMainLoopDispatch renamed MainLoopDispatch, since there's nothing intrinsic to glib about the idea. :)