Merge lp:unity-scopes-api/staging into lp:unity-scopes-api
- staging
- Merge into trunk
Proposed by
Michal Hruby
Status: | Merged |
---|---|
Merged at revision: | 205 |
Proposed branch: | lp:unity-scopes-api/staging |
Merge into: | lp:unity-scopes-api |
Diff against target: |
3746 lines (+2416/-313) 73 files modified
CMakeLists.txt (+1/-1) CONFIGFILES (+1/-1) RELEASE_NOTES.md (+6/-0) debian/changelog (+9/-0) debian/libunity-scopes1.symbols (+38/-4) demo/client.cpp (+5/-4) demo/scopes/scope-A/scope-A.cpp (+1/-1) doc/tutorial.dox (+44/-19) include/unity/scopes/OptionSelectorFilter.h (+8/-1) include/unity/scopes/RadioButtonsFilter.h (+124/-0) include/unity/scopes/RangeInputFilter.h (+1/-1) include/unity/scopes/RatingFilter.h (+180/-0) include/unity/scopes/internal/FilterBaseImpl.h (+1/-0) include/unity/scopes/internal/MWPublisher.h (+55/-0) include/unity/scopes/internal/MWSubscriber.h (+57/-0) include/unity/scopes/internal/MiddlewareBase.h (+5/-0) include/unity/scopes/internal/OptionSelectorFilterImpl.h (+3/-1) include/unity/scopes/internal/RadioButtonsFilterImpl.h (+50/-0) include/unity/scopes/internal/RatingFilterImpl.h (+64/-0) include/unity/scopes/internal/smartscopes/SmartScopesClient.h (+1/-0) include/unity/scopes/internal/zmq_middleware/ObjectAdapter.h (+0/-2) include/unity/scopes/internal/zmq_middleware/Util.h (+4/-0) include/unity/scopes/internal/zmq_middleware/ZmqMiddleware.h (+4/-1) include/unity/scopes/internal/zmq_middleware/ZmqPublisher.h (+83/-0) include/unity/scopes/internal/zmq_middleware/ZmqSubscriber.h (+86/-0) scoperegistry/CMakeLists.txt (+0/-1) scoperegistry/FindFiles.cpp (+17/-6) scoperegistry/FindFiles.h (+7/-3) scoperegistry/ScopeSet.cpp (+0/-124) scoperegistry/ScopeSet.h (+0/-56) scoperegistry/scoperegistry.cpp (+3/-4) scoperunner/scoperunner.cpp (+31/-1) src/scopes/CMakeLists.txt (+2/-0) src/scopes/OptionSelectorFilter.cpp (+7/-2) src/scopes/RadioButtonsFilter.cpp (+80/-0) src/scopes/RatingFilter.cpp (+105/-0) src/scopes/internal/CMakeLists.txt (+4/-0) src/scopes/internal/FilterBaseImpl.cpp (+60/-0) src/scopes/internal/MWPublisher.cpp (+42/-0) src/scopes/internal/MWSubscriber.cpp (+42/-0) src/scopes/internal/OptionSelectorFilterImpl.cpp (+32/-0) src/scopes/internal/RadioButtonsFilterImpl.cpp (+81/-0) src/scopes/internal/RatingFilterImpl.cpp (+109/-0) src/scopes/internal/SearchReplyImpl.cpp (+11/-1) src/scopes/internal/smartscopes/SSRegistryObject.cpp (+5/-0) src/scopes/internal/smartscopes/SmartScopesClient.cpp (+5/-0) src/scopes/internal/zmq_middleware/CMakeLists.txt (+2/-0) src/scopes/internal/zmq_middleware/ObjectAdapter.cpp (+0/-41) src/scopes/internal/zmq_middleware/Util.cpp (+42/-0) src/scopes/internal/zmq_middleware/ZmqMiddleware.cpp (+17/-4) src/scopes/internal/zmq_middleware/ZmqPublisher.cpp (+157/-0) src/scopes/internal/zmq_middleware/ZmqSubscriber.cpp (+185/-0) test/gtest/scopes/CMakeLists.txt (+2/-0) test/gtest/scopes/Filters/Filters_test.cpp (+72/-0) test/gtest/scopes/Filters/TestScope.h (+1/-1) test/gtest/scopes/IdleShutdown/IdleShutdown_test.cpp (+12/-6) test/gtest/scopes/IdleShutdown/SlowSearchScope.cpp (+1/-1) test/gtest/scopes/IdleShutdown/Zmq.ini.in (+5/-1) test/gtest/scopes/OptionSelectorFilter/OptionSelectorFilter_test.cpp (+3/-0) test/gtest/scopes/RadioButtonsFilter/CMakeLists.txt (+4/-0) test/gtest/scopes/RadioButtonsFilter/RadioButtonsFilter_test.cpp (+71/-0) test/gtest/scopes/RatingFilter/CMakeLists.txt (+4/-0) test/gtest/scopes/RatingFilter/RatingFilter_test.cpp (+111/-0) test/gtest/scopes/Registry/Registry_test.cpp (+0/-19) test/gtest/scopes/Registry/Zmq.ini.in (+1/-0) test/gtest/scopes/internal/smartscopes/SmartScopesClient/FakeSss.py (+1/-1) test/gtest/scopes/internal/smartscopes/SmartScopesClient/SmartScopesClient_test.cpp (+2/-0) test/gtest/scopes/internal/zmq_middleware/CMakeLists.txt (+1/-0) test/gtest/scopes/internal/zmq_middleware/ObjectAdapter/ObjectAdapter_test.cpp (+2/-4) test/gtest/scopes/internal/zmq_middleware/PubSub/CMakeLists.txt (+6/-0) test/gtest/scopes/internal/zmq_middleware/PubSub/PubSub_test.cpp (+237/-0) test/gtest/scopes/internal/zmq_middleware/PubSub/Zmq.ini.in (+2/-0) test/gtest/scopes/internal/zmq_middleware/RegistryI/RegistryI_test.cpp (+1/-1) |
To merge this branch: | bzr merge lp:unity-scopes-api/staging |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
PS Jenkins bot (community) | continuous-integration | Needs Fixing | |
Unity Team | Pending | ||
Review via email:
|
Commit message
Sync with devel.
Description of the change
Sync with devel.
To post a comment you must log in.
Revision history for this message
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
PS Jenkins bot (ps-jenkins) wrote : | # |
review:
Needs Fixing
(continuous-integration)
lp:unity-scopes-api/staging
updated
- 205. By Tarmac
-
Sync with devel.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'CMakeLists.txt' |
2 | --- CMakeLists.txt 2014-05-15 08:17:57 +0000 |
3 | +++ CMakeLists.txt 2014-05-21 14:02:43 +0000 |
4 | @@ -179,7 +179,7 @@ |
5 | # API version |
6 | set(UNITY_SCOPES_MAJOR 0) |
7 | set(UNITY_SCOPES_MINOR 4) |
8 | -set(UNITY_SCOPES_MICRO 6) |
9 | +set(UNITY_SCOPES_MICRO 7) |
10 | |
11 | # Version for testing, with all symbols visible |
12 | set(UNITY_SCOPES_TEST_LIB ${UNITY_SCOPES_LIB}-test) |
13 | |
14 | === modified file 'CONFIGFILES' |
15 | --- CONFIGFILES 2014-05-15 07:33:37 +0000 |
16 | +++ CONFIGFILES 2014-05-21 14:02:43 +0000 |
17 | @@ -279,7 +279,7 @@ |
18 | |
19 | If set, the results for this scope will be set to expire, and be refreshed. Valid values are: |
20 | |
21 | - - none |
22 | + - None |
23 | |
24 | - Small - in the order of a minute |
25 | |
26 | |
27 | === modified file 'RELEASE_NOTES.md' |
28 | --- RELEASE_NOTES.md 2014-05-15 10:34:30 +0000 |
29 | +++ RELEASE_NOTES.md 2014-05-21 14:02:43 +0000 |
30 | @@ -1,6 +1,12 @@ |
31 | Release notes |
32 | ============= |
33 | |
34 | +Changes in version 0.4.7 |
35 | +======================== |
36 | + - Implemented RatingFilter and RadioButtonsFilter. |
37 | + - changed create() methods of OptionSelectorFilter and RangeInputFilter to return unique_ptr (UPtr) |
38 | + instead of shared pointers. |
39 | + |
40 | Changes in version 0.4.6 |
41 | ======================== |
42 | - Added method to get and set display hints for filters (at this moment the only display hint |
43 | |
44 | === modified file 'debian/changelog' |
45 | --- debian/changelog 2014-05-19 10:10:28 +0000 |
46 | +++ debian/changelog 2014-05-21 14:02:43 +0000 |
47 | @@ -1,3 +1,12 @@ |
48 | +unity-scopes-api (0.4.7-0ubuntu1) UNRELEASED; urgency=medium |
49 | + |
50 | + [ Pawel Stolowski ] |
51 | + * Implemented RatingFilter and RadioButtonFilter. |
52 | + * Fixed lp:1319712: Appearance attributes not supported for remote scopes. |
53 | + * Changed create() methods of OptionSelectorFilter and RangeInputFilter to return unique ptr. |
54 | + |
55 | + -- Pawel Stolowski <pawel.stolowski@ubuntu.com> Fri, 16 May 2014 17:48:23 +0200 |
56 | + |
57 | unity-scopes-api (0.4.6+14.10.20140519-0ubuntu1) utopic; urgency=medium |
58 | |
59 | [ Pete Woods ] |
60 | |
61 | === modified file 'debian/libunity-scopes1.symbols' |
62 | --- debian/libunity-scopes1.symbols 2014-05-19 10:10:27 +0000 |
63 | +++ debian/libunity-scopes1.symbols 2014-05-21 14:02:43 +0000 |
64 | @@ -82,6 +82,14 @@ |
65 | (c++)"unity::scopes::ListenerBase::~ListenerBase()@Base" 0.4.0+14.04.20140312.1 |
66 | (c++)"unity::scopes::PreviewReply::PreviewReply()@Base" 0.4.0+14.04.20140312.1 |
67 | (c++)"unity::scopes::PreviewReply::~PreviewReply()@Base" 0.4.0+14.04.20140312.1 |
68 | + (c++)"unity::scopes::RatingFilter::add_option(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@Base" 0replaceme |
69 | + (c++)"unity::scopes::RatingFilter::set_on_icon(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@Base" 0replaceme |
70 | + (c++)"unity::scopes::RatingFilter::set_off_icon(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@Base" 0replaceme |
71 | + (c++)"unity::scopes::RatingFilter::update_state(unity::scopes::FilterState&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, bool)@Base" 0replaceme |
72 | + (c++)"unity::scopes::RatingFilter::create(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@Base" 0replaceme |
73 | + (c++)"unity::scopes::RatingFilter::create(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int)@Base" 0replaceme |
74 | + (c++)"unity::scopes::RatingFilter::RatingFilter(unity::scopes::internal::RatingFilterImpl*)@Base" 0replaceme |
75 | + (c++)"unity::scopes::RatingFilter::~RatingFilter()@Base" 0replaceme |
76 | (c++)"unity::scopes::PreviewWidget::add_attribute_value(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unity::scopes::Variant const&)@Base" 0.4.0+14.04.20140312.1 |
77 | (c++)"unity::scopes::PreviewWidget::add_attribute_mapping(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@Base" 0.4.0+14.04.20140312.1 |
78 | (c++)"unity::scopes::PreviewWidget::PreviewWidget(unity::scopes::PreviewWidget&&)@Base" 0.4.0+14.04.20140312.1 |
79 | @@ -216,6 +224,11 @@ |
80 | (c++)"unity::scopes::ActivationResponse::~ActivationResponse()@Base" 0.4.0+14.04.20140312.1 |
81 | (c++)"unity::scopes::ActivationResponse::operator=(unity::scopes::ActivationResponse&&)@Base" 0.4.0+14.04.20140312.1 |
82 | (c++)"unity::scopes::ActivationResponse::operator=(unity::scopes::ActivationResponse const&)@Base" 0.4.0+14.04.20140312.1 |
83 | + (c++)"unity::scopes::RadioButtonsFilter::add_option(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@Base" 0replaceme |
84 | + (c++)"unity::scopes::RadioButtonsFilter::update_state(unity::scopes::FilterState&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, bool)@Base" 0replaceme |
85 | + (c++)"unity::scopes::RadioButtonsFilter::create(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@Base" 0replaceme |
86 | + (c++)"unity::scopes::RadioButtonsFilter::RadioButtonsFilter(unity::scopes::internal::RadioButtonsFilterImpl*)@Base" 0replaceme |
87 | + (c++)"unity::scopes::RadioButtonsFilter::~RadioButtonsFilter()@Base" 0replaceme |
88 | (c++)"unity::scopes::SearchListenerBase::push(unity::scopes::Annotation)@Base" 0.4.0+14.04.20140312.1 |
89 | (c++)"unity::scopes::SearchListenerBase::push(std::list<unity::scopes::Department, std::allocator<unity::scopes::Department> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@Base" 0.4.0+14.04.20140312.1 |
90 | (c++)"unity::scopes::SearchListenerBase::push(std::list<std::shared_ptr<unity::scopes::FilterBase const>, std::allocator<std::shared_ptr<unity::scopes::FilterBase const> > > const&, unity::scopes::FilterState const&)@Base" 0.4.0+14.04.20140312.1 |
91 | @@ -447,13 +460,12 @@ |
92 | (c++)"unity::scopes::internal::ScopeMetadataImpl::set_search_hint(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@Base" 0.4.0+14.04.20140312.1 |
93 | (c++)"unity::scopes::internal::ScopeMetadataImpl::set_display_name(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@Base" 0.4.0+14.04.20140312.1 |
94 | (c++)"unity::scopes::internal::ScopeMetadataImpl::set_scope_directory(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@Base" 0.4.2+14.04.20140404.2 |
95 | + (c++)"unity::scopes::internal::ScopeMetadataImpl::set_results_ttl_type(unity::scopes::ScopeMetadata::ResultsTtlType)@Base" 0.4.6+14.10.20140519 |
96 | (c++)"unity::scopes::internal::ScopeMetadataImpl::set_appearance_attributes(std::map<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, unity::scopes::Variant, std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const, unity::scopes::Variant> > > const&)@Base" 0.4.2+14.04.20140404.2 |
97 | (c++)"unity::scopes::internal::ScopeMetadataImpl::create(std::unique_ptr<unity::scopes::internal::ScopeMetadataImpl, std::default_delete<unity::scopes::internal::ScopeMetadataImpl> >)@Base" 0.4.0+14.04.20140312.1 |
98 | (c++)"unity::scopes::internal::ScopeMetadataImpl::set_art(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@Base" 0.4.0+14.04.20140312.1 |
99 | (c++)"unity::scopes::internal::ScopeMetadataImpl::set_icon(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@Base" 0.4.0+14.04.20140312.1 |
100 | (c++)"unity::scopes::internal::ScopeMetadataImpl::set_proxy(std::shared_ptr<unity::scopes::Scope> const&)@Base" 0.4.0+14.04.20140312.1 |
101 | - (c++)"unity::scopes::internal::ScopeMetadataImpl::set_results_ttl_type(unity::scopes::ScopeMetadata::ResultsTtlType)@Base" 0.4.6+14.10.20140519 |
102 | - (c++)"unity::scopes::internal::ScopeMetadataImpl::results_ttl_type() const@Base" 0.4.6+14.10.20140519 |
103 | (c++)"unity::scopes::internal::ScopeMetadataImpl::ScopeMetadataImpl(unity::scopes::internal::MiddlewareBase*)@Base" 0.4.0+14.04.20140312.1 |
104 | (c++)"unity::scopes::internal::ScopeMetadataImpl::ScopeMetadataImpl(unity::scopes::internal::ScopeMetadataImpl const&)@Base" 0.4.0+14.04.20140312.1 |
105 | (c++)"unity::scopes::internal::ScopeMetadataImpl::ScopeMetadataImpl(std::map<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, unity::scopes::Variant, std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const, unity::scopes::Variant> > > const&, unity::scopes::internal::MiddlewareBase*)@Base" 0.4.0+14.04.20140312.1 |
106 | @@ -522,6 +534,14 @@ |
107 | (c++)"unity::scopes::ColumnLayout::serialize() const@Base" 0.4.0+14.04.20140312.1 |
108 | (c++)"unity::scopes::FilterOption::id() const@Base" 0.4.0+14.04.20140312.1 |
109 | (c++)"unity::scopes::FilterOption::label() const@Base" 0.4.0+14.04.20140312.1 |
110 | + (c++)"unity::scopes::RatingFilter::update_state(unity::scopes::FilterState&, std::shared_ptr<unity::scopes::FilterOption const>, bool) const@Base" 0replaceme |
111 | + (c++)"unity::scopes::RatingFilter::active_rating(unity::scopes::FilterState const&) const@Base" 0replaceme |
112 | + (c++)"unity::scopes::RatingFilter::has_active_rating(unity::scopes::FilterState const&) const@Base" 0replaceme |
113 | + (c++)"unity::scopes::RatingFilter::fwd() const@Base" 0replaceme |
114 | + (c++)"unity::scopes::RatingFilter::label() const@Base" 0replaceme |
115 | + (c++)"unity::scopes::RatingFilter::on_icon() const@Base" 0replaceme |
116 | + (c++)"unity::scopes::RatingFilter::options() const@Base" 0replaceme |
117 | + (c++)"unity::scopes::RatingFilter::off_icon() const@Base" 0replaceme |
118 | (c++)"unity::scopes::PreviewWidget::widget_type() const@Base" 0.4.0+14.04.20140312.1 |
119 | (c++)"unity::scopes::PreviewWidget::attribute_values() const@Base" 0.4.0+14.04.20140312.1 |
120 | (c++)"unity::scopes::PreviewWidget::attribute_mappings() const@Base" 0.4.0+14.04.20140312.1 |
121 | @@ -532,6 +552,7 @@ |
122 | (c++)"unity::scopes::ScopeMetadata::search_hint() const@Base" 0.4.0+14.04.20140312.1 |
123 | (c++)"unity::scopes::ScopeMetadata::display_name() const@Base" 0.4.0+14.04.20140312.1 |
124 | (c++)"unity::scopes::ScopeMetadata::scope_directory() const@Base" 0.4.2+14.04.20140404.2 |
125 | + (c++)"unity::scopes::ScopeMetadata::results_ttl_type() const@Base" 0.4.6+14.10.20140519 |
126 | (c++)"unity::scopes::ScopeMetadata::appearance_attributes() const@Base" 0.4.2+14.04.20140404.2 |
127 | (c++)"unity::scopes::ScopeMetadata::art() const@Base" 0.4.0+14.04.20140312.1 |
128 | (c++)"unity::scopes::ScopeMetadata::icon() const@Base" 0.4.0+14.04.20140312.1 |
129 | @@ -541,7 +562,6 @@ |
130 | (c++)"unity::scopes::ScopeMetadata::scope_id() const@Base" 0.4.0+14.04.20140312.1 |
131 | (c++)"unity::scopes::ScopeMetadata::invisible() const@Base" 0.4.0+14.04.20140312.1 |
132 | (c++)"unity::scopes::ScopeMetadata::serialize() const@Base" 0.4.0+14.04.20140312.1 |
133 | - (c++)"unity::scopes::ScopeMetadata::results_ttl_type() const@Base" 0.4.6+14.10.20140519 |
134 | (c++)"unity::scopes::ActionMetadata::scope_data() const@Base" 0.4.0+14.04.20140312.1 |
135 | (c++)"unity::scopes::ActionMetadata::form_factor() const@Base" 0.4.0+14.04.20140312.1 |
136 | (c++)"unity::scopes::ActionMetadata::locale() const@Base" 0.4.0+14.04.20140312.1 |
137 | @@ -573,10 +593,17 @@ |
138 | (c++)"unity::scopes::ActivationResponse::query() const@Base" 0.4.0+14.04.20140312.1 |
139 | (c++)"unity::scopes::ActivationResponse::status() const@Base" 0.4.0+14.04.20140312.1 |
140 | (c++)"unity::scopes::ActivationResponse::serialize() const@Base" 0.4.0+14.04.20140312.1 |
141 | + (c++)"unity::scopes::RadioButtonsFilter::update_state(unity::scopes::FilterState&, std::shared_ptr<unity::scopes::FilterOption const>, bool) const@Base" 0replaceme |
142 | + (c++)"unity::scopes::RadioButtonsFilter::active_option(unity::scopes::FilterState const&) const@Base" 0replaceme |
143 | + (c++)"unity::scopes::RadioButtonsFilter::has_active_option(unity::scopes::FilterState const&) const@Base" 0replaceme |
144 | + (c++)"unity::scopes::RadioButtonsFilter::fwd() const@Base" 0replaceme |
145 | + (c++)"unity::scopes::RadioButtonsFilter::label() const@Base" 0replaceme |
146 | + (c++)"unity::scopes::RadioButtonsFilter::options() const@Base" 0replaceme |
147 | (c++)"unity::scopes::MiddlewareException::self() const@Base" 0.4.0+14.04.20140312.1 |
148 | (c++)"unity::scopes::OptionSelectorFilter::multi_select() const@Base" 0.4.0+14.04.20140312.1 |
149 | (c++)"unity::scopes::OptionSelectorFilter::update_state(unity::scopes::FilterState&, std::shared_ptr<unity::scopes::FilterOption const>, bool) const@Base" 0.4.0+14.04.20140312.1 |
150 | (c++)"unity::scopes::OptionSelectorFilter::active_options(unity::scopes::FilterState const&) const@Base" 0.4.0+14.04.20140312.1 |
151 | + (c++)"unity::scopes::OptionSelectorFilter::has_active_option(unity::scopes::FilterState const&) const@Base" 0replaceme |
152 | (c++)"unity::scopes::OptionSelectorFilter::fwd() const@Base" 0.4.0+14.04.20140312.1 |
153 | (c++)"unity::scopes::OptionSelectorFilter::label() const@Base" 0.4.0+14.04.20140312.1 |
154 | (c++)"unity::scopes::OptionSelectorFilter::options() const@Base" 0.4.0+14.04.20140312.1 |
155 | @@ -644,13 +671,13 @@ |
156 | (c++)"unity::scopes::internal::ScopeConfig::idle_timeout() const@Base" 0.4.5+14.10.20140513 |
157 | (c++)"unity::scopes::internal::ScopeConfig::overrideable() const@Base" 0.4.0+14.04.20140312.1 |
158 | (c++)"unity::scopes::internal::ScopeConfig::scope_runner() const@Base" 0.4.2+14.04.20140404.2 |
159 | + (c++)"unity::scopes::internal::ScopeConfig::results_ttl_type() const@Base" 0.4.6+14.10.20140519 |
160 | (c++)"unity::scopes::internal::ScopeConfig::appearance_attributes() const@Base" 0.4.2+14.04.20140404.2 |
161 | (c++)"unity::scopes::internal::ScopeConfig::art() const@Base" 0.4.0+14.04.20140312.1 |
162 | (c++)"unity::scopes::internal::ScopeConfig::icon() const@Base" 0.4.0+14.04.20140312.1 |
163 | (c++)"unity::scopes::internal::ScopeConfig::author() const@Base" 0.4.0+14.04.20140312.1 |
164 | (c++)"unity::scopes::internal::ScopeConfig::hot_key() const@Base" 0.4.0+14.04.20140312.1 |
165 | (c++)"unity::scopes::internal::ScopeConfig::invisible() const@Base" 0.4.0+14.04.20140312.1 |
166 | - (c++)"unity::scopes::internal::ScopeConfig::results_ttl_type() const@Base" 0.4.6+14.10.20140519 |
167 | (c++)"unity::scopes::internal::ScopeLoader::scope_base() const@Base" 0.4.0+14.04.20140312.1 |
168 | (c++)"unity::scopes::internal::ScopeLoader::libpath() const@Base" 0.4.0+14.04.20140312.1 |
169 | (c++)"unity::scopes::internal::ScopeLoader::scope_id() const@Base" 0.4.2+14.04.20140404.2 |
170 | @@ -693,6 +720,7 @@ |
171 | (c++)"unity::scopes::internal::ScopeMetadataImpl::search_hint() const@Base" 0.4.0+14.04.20140312.1 |
172 | (c++)"unity::scopes::internal::ScopeMetadataImpl::display_name() const@Base" 0.4.0+14.04.20140312.1 |
173 | (c++)"unity::scopes::internal::ScopeMetadataImpl::scope_directory() const@Base" 0.4.2+14.04.20140404.2 |
174 | + (c++)"unity::scopes::internal::ScopeMetadataImpl::results_ttl_type() const@Base" 0.4.6+14.10.20140519 |
175 | (c++)"unity::scopes::internal::ScopeMetadataImpl::appearance_attributes() const@Base" 0.4.2+14.04.20140404.2 |
176 | (c++)"unity::scopes::internal::ScopeMetadataImpl::art() const@Base" 0.4.0+14.04.20140312.1 |
177 | (c++)"unity::scopes::internal::ScopeMetadataImpl::icon() const@Base" 0.4.0+14.04.20140312.1 |
178 | @@ -710,6 +738,7 @@ |
179 | (c++)"typeinfo for unity::scopes::SearchReply@Base" 0.4.0+14.04.20140312.1 |
180 | (c++)"typeinfo for unity::scopes::ListenerBase@Base" 0.4.0+14.04.20140312.1 |
181 | (c++)"typeinfo for unity::scopes::PreviewReply@Base" 0.4.0+14.04.20140312.1 |
182 | + (c++)"typeinfo for unity::scopes::RatingFilter@Base" 0replaceme |
183 | (c++)"typeinfo for unity::scopes::PreviewWidget@Base" 0.4.0+14.04.20140312.1 |
184 | (c++)"typeinfo for unity::scopes::VariantBuilder@Base" 0.4.0+14.04.20140312.1 |
185 | (c++)"typeinfo for unity::scopes::ConfigException@Base" 0.4.0+14.04.20140312.1 |
186 | @@ -720,6 +749,7 @@ |
187 | (c++)"typeinfo for unity::scopes::TimeoutException@Base" 0.4.0+14.04.20140312.1 |
188 | (c++)"typeinfo for unity::scopes::CategorisedResult@Base" 0.4.0+14.04.20140312.1 |
189 | (c++)"typeinfo for unity::scopes::NotFoundException@Base" 0.4.0+14.04.20140312.1 |
190 | + (c++)"typeinfo for unity::scopes::RadioButtonsFilter@Base" 0replaceme |
191 | (c++)"typeinfo for unity::scopes::SearchListenerBase@Base" 0.4.0+14.04.20140312.1 |
192 | (c++)"typeinfo for unity::scopes::ActivationQueryBase@Base" 0.4.0+14.04.20140312.1 |
193 | (c++)"typeinfo for unity::scopes::MiddlewareException@Base" 0.4.0+14.04.20140312.1 |
194 | @@ -748,6 +778,7 @@ |
195 | (c++)"typeinfo name for unity::scopes::SearchReply@Base" 0.4.0+14.04.20140312.1 |
196 | (c++)"typeinfo name for unity::scopes::ListenerBase@Base" 0.4.0+14.04.20140312.1 |
197 | (c++)"typeinfo name for unity::scopes::PreviewReply@Base" 0.4.0+14.04.20140312.1 |
198 | + (c++)"typeinfo name for unity::scopes::RatingFilter@Base" 0replaceme |
199 | (c++)"typeinfo name for unity::scopes::PreviewWidget@Base" 0.4.0+14.04.20140312.1 |
200 | (c++)"typeinfo name for unity::scopes::VariantBuilder@Base" 0.4.0+14.04.20140312.1 |
201 | (c++)"typeinfo name for unity::scopes::ConfigException@Base" 0.4.0+14.04.20140312.1 |
202 | @@ -758,6 +789,7 @@ |
203 | (c++)"typeinfo name for unity::scopes::TimeoutException@Base" 0.4.0+14.04.20140312.1 |
204 | (c++)"typeinfo name for unity::scopes::CategorisedResult@Base" 0.4.0+14.04.20140312.1 |
205 | (c++)"typeinfo name for unity::scopes::NotFoundException@Base" 0.4.0+14.04.20140312.1 |
206 | + (c++)"typeinfo name for unity::scopes::RadioButtonsFilter@Base" 0replaceme |
207 | (c++)"typeinfo name for unity::scopes::SearchListenerBase@Base" 0.4.0+14.04.20140312.1 |
208 | (c++)"typeinfo name for unity::scopes::ActivationQueryBase@Base" 0.4.0+14.04.20140312.1 |
209 | (c++)"typeinfo name for unity::scopes::MiddlewareException@Base" 0.4.0+14.04.20140312.1 |
210 | @@ -797,6 +829,7 @@ |
211 | (c++)"vtable for unity::scopes::SearchReply@Base" 0.4.0+14.04.20140312.1 |
212 | (c++)"vtable for unity::scopes::ListenerBase@Base" 0.4.0+14.04.20140312.1 |
213 | (c++)"vtable for unity::scopes::PreviewReply@Base" 0.4.0+14.04.20140312.1 |
214 | + (c++)"vtable for unity::scopes::RatingFilter@Base" 0replaceme |
215 | (c++)"vtable for unity::scopes::PreviewWidget@Base" 0.4.0+14.04.20140312.1 |
216 | (c++)"vtable for unity::scopes::VariantBuilder@Base" 0.4.0+14.04.20140312.1 |
217 | (c++)"vtable for unity::scopes::ConfigException@Base" 0.4.0+14.04.20140312.1 |
218 | @@ -807,6 +840,7 @@ |
219 | (c++)"vtable for unity::scopes::TimeoutException@Base" 0.4.0+14.04.20140312.1 |
220 | (c++)"vtable for unity::scopes::CategorisedResult@Base" 0.4.0+14.04.20140312.1 |
221 | (c++)"vtable for unity::scopes::NotFoundException@Base" 0.4.0+14.04.20140312.1 |
222 | + (c++)"vtable for unity::scopes::RadioButtonsFilter@Base" 0replaceme |
223 | (c++)"vtable for unity::scopes::SearchListenerBase@Base" 0.4.0+14.04.20140312.1 |
224 | (c++)"vtable for unity::scopes::ActivationQueryBase@Base" 0.4.0+14.04.20140312.1 |
225 | (c++)"vtable for unity::scopes::MiddlewareException@Base" 0.4.0+14.04.20140312.1 |
226 | |
227 | === modified file 'demo/client.cpp' |
228 | --- demo/client.cpp 2014-04-29 13:51:44 +0000 |
229 | +++ demo/client.cpp 2014-05-21 14:02:43 +0000 |
230 | @@ -422,10 +422,11 @@ |
231 | } |
232 | |
233 | auto meta = r->get_metadata(scope_id); |
234 | - cout << "Scope metadata: " << endl; |
235 | - cout << "\tscope_id: " << meta.scope_id() << endl; |
236 | - cout << "\tdisplay_name: " << meta.display_name() << endl; |
237 | - cout << "\tdescription: " << meta.description() << endl; |
238 | + cout << "Scope metadata: " << endl; |
239 | + cout << "\tscope_id: " << meta.scope_id() << endl; |
240 | + cout << "\tdisplay_name: " << meta.display_name() << endl; |
241 | + cout << "\tdescription: " << meta.description() << endl; |
242 | + cout << "\tappearance attr: " << to_string(Variant(meta.appearance_attributes())) << endl; |
243 | string tmp; |
244 | try |
245 | { |
246 | |
247 | === modified file 'demo/scopes/scope-A/scope-A.cpp' |
248 | --- demo/scopes/scope-A/scope-A.cpp 2014-04-29 11:20:57 +0000 |
249 | +++ demo/scopes/scope-A/scope-A.cpp 2014-05-21 14:02:43 +0000 |
250 | @@ -59,7 +59,7 @@ |
251 | reply->register_departments(departments); |
252 | |
253 | Filters filters; |
254 | - auto filter = OptionSelectorFilter::create("f1", "Options"); |
255 | + OptionSelectorFilter::SPtr filter = OptionSelectorFilter::create("f1", "Options"); |
256 | filter->add_option("1", "Option 1"); |
257 | filter->add_option("2", "Option 2"); |
258 | filters.push_back(filter); |
259 | |
260 | === modified file 'doc/tutorial.dox' |
261 | --- doc/tutorial.dox 2014-05-08 10:47:45 +0000 |
262 | +++ doc/tutorial.dox 2014-05-21 14:02:43 +0000 |
263 | @@ -188,7 +188,7 @@ |
264 | and \link unity::scopes::SearchReply::push push\endlink. |
265 | |
266 | The \link unity::scopes::SearchReply::register_category register_category\endlink method is a factory method for creating new categories (see |
267 | -\link unity::scopes::Category\endlink). Categories can be created at any point during query processing inside run method, but it's recommended to create |
268 | +\link unity::scopes::Category\endlink). Categories can be created at any point during query processing inside run method, but we recommend to create |
269 | them as soon as possible (ideally as soon as they are known to the scope). |
270 | |
271 | When creating a category, one of its parameters is a \link unity::scopes::CategoryRenderer \endlink instance, |
272 | @@ -552,29 +552,39 @@ |
273 | restart scope-registry |
274 | \endverbatim |
275 | |
276 | -The scope will be installed under one of the "scopes directories" |
277 | +Scopes are installed under one of the "scopes directories" |
278 | scanned by the scope registry. Currently these default to: |
279 | |
280 | <ul> |
281 | <li>/usr/lib/${arch}/unity-scopes</li> |
282 | <li>/custom/lib/${arch}/unity-scopes</li> |
283 | -<!-- <li>??? Click packages?</li> --> |
284 | +<li>$HOME/.local/share/unity-scopes</li> |
285 | </ul> |
286 | |
287 | -Individual scopes are installed into a subdirectory matching the |
288 | -scope's name. At a minimum, the directory structure should contain |
289 | -the following: |
290 | +The `/usr/lib` directory is for scopes that are pre-installed by Canonical. |
291 | +The `/custom/lib` directory is for scopes that pre-installed by OEMs. |
292 | +The `$HOME/.local` directory is for scopes that are installed from click packages. |
293 | + |
294 | +Individual scopes are installed into subdirectories of these |
295 | +installation directories. The name of the subdirectory containing |
296 | +a scope's `.ini` and `.so` files can be anything but, to avoid name clashes, |
297 | +we strongly suggest something that is unique, such as `com.canonical.scopes.scopename`. |
298 | +At a minimum, the directory structure must contain the following: |
299 | |
300 | -+- ${scopesdir} |
301 | - `-+- scopename |
302 | + `-+- subdirectory |
303 | |--- scopename.ini |
304 | - `--- libscopename.so |
305 | + `--- <library>.so |
306 | |
307 | -That is, a scope metadata file and a shared library containing the |
308 | -scope code. The scope author is free to ship additional data in this |
309 | +That is, each subdirectory must contain a scope `.ini` file and a shared library containing the |
310 | +scope code. The scope author is free to ship additional data in this |
311 | directory (e.g. icons and screenshots). |
312 | |
313 | -The scope metadata file uses the standard ini file format, with the |
314 | +The name of the scope's `.ini` file _must_ be a unique ID for the scope. We _strongly_ |
315 | +suggest to use a unique identifier, such as `com.canonical.scopes.scopename`, to avoid |
316 | +clashes with scopes created by other developers. |
317 | + |
318 | +The scope `.ini` file uses the standard `.ini` file format, with the |
319 | following keys: |
320 | |
321 | [ScopeConfig] |
322 | @@ -585,8 +595,22 @@ |
323 | Art = path to screenshot of the scope |
324 | SearchHint = hint text displayed to user when viewing scope |
325 | HotKey = |
326 | - |
327 | -In addition to allowing the registry to make the scope available, this information controls how the scope appears in the "Scopes" scope. |
328 | + ResultsTtlType = None, Small, Medium, or Large |
329 | + |
330 | + [Appearance] |
331 | + TODO: document valid attributes |
332 | + |
333 | +The `ScopeConfig` group is mandatory and must contain settings for at least `DisplayName`, `Description`, and Author. |
334 | +`DisplayName` and `Description` can (and should) be localized. For example: |
335 | + |
336 | +`Description[de] = Fußballergebnisse` |
337 | + |
338 | +In addition to allowing the registry to make the scope available, this information controls how the scope appears |
339 | +in the "Scopes" scope. |
340 | + |
341 | +The name of of the scope's `.so` file can be `libscopename.so`, `scopename.so`, or simply `scope.so`. For example, |
342 | +for a scope named `Fred`, the names `libFred.so`, `Fred.so`, and `scope.so` are acceptable. (No other library |
343 | +names are valid.) |
344 | |
345 | \subsection scopetool Previewing scope |
346 | |
347 | @@ -599,16 +623,17 @@ |
348 | sudo apt-get install unity-scope-tool |
349 | \endverbatim |
350 | |
351 | -After installation, you can run the scope-tool with a parameter specifying |
352 | -path to your scope configuration file (for example `unity-scope-tool ~/dev/myscope/build/myscope.ini`). If a binary for your scope can be found in the same |
353 | -directory (ie there's `~/dev/myscope/build/libmyscope.so`), the scope-tool will |
354 | +After installation, you can run the scope-tool with a parameter specifying the |
355 | +path to your scope configuration file (for example `unity-scope-tool ~/dev/myscope/build/myscope.ini`). |
356 | +If a binary for your scope can be found in the same |
357 | +directory, the scope-tool will |
358 | display surfacing and search results provided by your scope, and allow you to |
359 | perform searches, invoke previews and actions within previews. |
360 | |
361 | -Note that the scope-tool is using the same rendering mechanism as Unity |
362 | -itself, and therefore what you see in the scope-tool is what you get in Unity. |
363 | +Note that the scope-tool uses the same rendering mechanism as Unity |
364 | +itself and, therefore, what you see in the scope-tool is what you get in Unity. |
365 | It can also be used to fine-tune the category definitions, as it allows you |
366 | -to manipulate the definitions on the fly, and once you're happy with the result |
367 | +to manipulate the definitions on the fly. Once you are happy with the result |
368 | you can just copy the JSON definition back into your scope |
369 | (see unity::scopes::CategoryRenderer::CategoryRenderer()). |
370 | |
371 | |
372 | === modified file 'include/unity/scopes/OptionSelectorFilter.h' |
373 | --- include/unity/scopes/OptionSelectorFilter.h 2014-05-08 16:10:18 +0000 |
374 | +++ include/unity/scopes/OptionSelectorFilter.h 2014-05-21 14:02:43 +0000 |
375 | @@ -57,7 +57,7 @@ |
376 | \param multi_select If true, the filter permits more than option to be selected; otherwise, only a single |
377 | option can be selected. |
378 | */ |
379 | - static OptionSelectorFilter::SPtr create(std::string const& id, std::string const& label, bool multi_select = false); |
380 | + static OptionSelectorFilter::UPtr create(std::string const& id, std::string const& label, bool multi_select = false); |
381 | |
382 | /** |
383 | \brief Get the label of this filter. |
384 | @@ -84,6 +84,13 @@ |
385 | std::list<FilterOption::SCPtr> options() const; |
386 | |
387 | /** |
388 | + \brief Check if an option is active for this filter. |
389 | + \param filter_state The state of filters |
390 | + \return true if an option is active |
391 | + */ |
392 | + bool has_active_option(FilterState const& filter_state) const; |
393 | + |
394 | + /** |
395 | \brief Get active options from an instance of FilterState for this filter. |
396 | \return The set of selected filter options. |
397 | */ |
398 | |
399 | === added file 'include/unity/scopes/RadioButtonsFilter.h' |
400 | --- include/unity/scopes/RadioButtonsFilter.h 1970-01-01 00:00:00 +0000 |
401 | +++ include/unity/scopes/RadioButtonsFilter.h 2014-05-21 14:02:43 +0000 |
402 | @@ -0,0 +1,124 @@ |
403 | +/* |
404 | + * Copyright (C) 2014 Canonical Ltd |
405 | + * |
406 | + * This program is free software: you can redistribute it and/or modify |
407 | + * it under the terms of the GNU Lesser General Public License version 3 as |
408 | + * published by the Free Software Foundation. |
409 | + * |
410 | + * This program is distributed in the hope that it will be useful, |
411 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
412 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
413 | + * GNU Lesser General Public License for more details. |
414 | + * |
415 | + * You should have received a copy of the GNU Lesser General Public License |
416 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
417 | + * |
418 | + * Authored by: Pawel Stolowski <pawel.stolowski@canonical.com> |
419 | + */ |
420 | + |
421 | +#ifndef UNITY_SCOPES_RADIOBUTTONSFILTER_H |
422 | +#define UNITY_SCOPES_RADIOBUTTONSFILTER_H |
423 | + |
424 | +#include <unity/scopes/FilterBase.h> |
425 | +#include <unity/scopes/FilterOption.h> |
426 | + |
427 | +namespace unity |
428 | +{ |
429 | + |
430 | +namespace scopes |
431 | +{ |
432 | + |
433 | +class FilterState; |
434 | + |
435 | +namespace internal |
436 | +{ |
437 | + |
438 | +class RadioButtonsFilterImpl; |
439 | + |
440 | +} |
441 | + |
442 | +/** |
443 | +\brief A filter that displays mutually exclusive list of options. |
444 | + |
445 | +Displays filter with a set of options and allows only one option to be selected at a time. |
446 | +*/ |
447 | +class UNITY_API RadioButtonsFilter : public FilterBase |
448 | +{ |
449 | +public: |
450 | +/// @cond |
451 | + UNITY_DEFINES_PTRS(RadioButtonsFilter); |
452 | +/// @endcond |
453 | + |
454 | + /** |
455 | + \brief Creates RadioButtonsFilter filter. |
456 | + |
457 | + Creates an empty RadioButtonsFilter filter. Use unity::scopes::RadioButtonsFilter::add_option() to add options to it. |
458 | + \param id A unique identifier for the filter that can be used to identify it later among several filters. |
459 | + \param label A display label for this filter |
460 | + \return Instance of RadioButtonsFilter |
461 | + */ |
462 | + static RadioButtonsFilter::UPtr create(std::string const& id, std::string const& label); |
463 | + |
464 | + /** |
465 | + \brief Adds a new option to the filter. |
466 | + |
467 | + \param id A unique identifier of the option. |
468 | + \param label A display label for the option |
469 | + \return Instance of FilterOption |
470 | + */ |
471 | + FilterOption::SCPtr add_option(std::string const& id, std::string const& label); |
472 | + |
473 | + /** |
474 | + \brief Get the label of this filter. |
475 | + \return The filter label. |
476 | + */ |
477 | + std::string label() const; |
478 | + |
479 | + /** |
480 | + \brief Get active option from an instance of FilterState for this filter. |
481 | + \return The active option or nullptr if no option is active. |
482 | + */ |
483 | + FilterOption::SCPtr active_option(FilterState const& filter_state) const; |
484 | + |
485 | + /** |
486 | + \brief Check if active options. |
487 | + \param filter_state The state of filters |
488 | + \return true if there is at least one option active |
489 | + */ |
490 | + bool has_active_option(FilterState const& filter_state) const; |
491 | + |
492 | + |
493 | + /** |
494 | + \brief Get all options of this filter, in the order they were added. |
495 | + \return The list of options. |
496 | + */ |
497 | + std::list<FilterOption::SCPtr> options() const; |
498 | + |
499 | + /** |
500 | + \brief Marks given FilterOption of this filter instance as active (or not active) in a FilterState object. |
501 | + |
502 | + Records the given FilterOption as "selected" in the FilterState. This is meant to be used to modify a |
503 | + FilterState received with a search request before sending it back to the client (UI shell). |
504 | + Only one option can be active at a time - marking an option active automatically deactivates any other option. |
505 | + */ |
506 | + void update_state(FilterState& filter_state, FilterOption::SCPtr option, bool active) const; |
507 | + |
508 | + /** |
509 | + \brief Marks an option of a filter active/inactive in a FilterState object, without having an instance of OptionSelectorFilter. |
510 | + |
511 | + Updates an instance of FilterState, without the need for an OptionSelectorFilter instance. This is meant |
512 | + to be used when creating a canned Query that references another scope. |
513 | + */ |
514 | + static void update_state(FilterState& filter_state, std::string const& filter_id, std::string const& option_id, bool value); |
515 | + |
516 | +private: |
517 | + RadioButtonsFilter(internal::RadioButtonsFilterImpl*); |
518 | + internal::RadioButtonsFilterImpl* fwd() const; |
519 | + friend class internal::RadioButtonsFilterImpl; |
520 | +}; |
521 | + |
522 | +} // namespace scopes |
523 | + |
524 | +} // namespace unity |
525 | + |
526 | +#endif |
527 | |
528 | === modified file 'include/unity/scopes/RangeInputFilter.h' |
529 | --- include/unity/scopes/RangeInputFilter.h 2014-05-09 11:26:27 +0000 |
530 | +++ include/unity/scopes/RangeInputFilter.h 2014-05-21 14:02:43 +0000 |
531 | @@ -124,10 +124,10 @@ |
532 | \brief Store start and end value in the filter state, without having an instance of RangeInputFilter. |
533 | |
534 | Updates filter_state with start and end values without an instance of RangeInputFilter. This is meant |
535 | + for the explanation of this method. |
536 | to be used when creating a CannedQuery that points to a foreign scope. |
537 | |
538 | See the documentation of unity::scopes::update_state(FilterState const& filter_state, Variant const& start_value, Variant const& end_value) |
539 | - for the explanation of this method. |
540 | |
541 | \param filter_state FilterState instance to update |
542 | \param filter_id Unique identifier of filter |
543 | |
544 | === added file 'include/unity/scopes/RatingFilter.h' |
545 | --- include/unity/scopes/RatingFilter.h 1970-01-01 00:00:00 +0000 |
546 | +++ include/unity/scopes/RatingFilter.h 2014-05-21 14:02:43 +0000 |
547 | @@ -0,0 +1,180 @@ |
548 | +/* |
549 | + * Copyright (C) 2014 Canonical Ltd |
550 | + * |
551 | + * This program is free software: you can redistribute it and/or modify |
552 | + * it under the terms of the GNU Lesser General Public License version 3 as |
553 | + * published by the Free Software Foundation. |
554 | + * |
555 | + * This program is distributed in the hope that it will be useful, |
556 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
557 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
558 | + * GNU Lesser General Public License for more details. |
559 | + * |
560 | + * You should have received a copy of the GNU Lesser General Public License |
561 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
562 | + * |
563 | + * Authored by: Pawel Stolowski <pawel.stolowski@canonical.com> |
564 | + */ |
565 | + |
566 | +#ifndef UNITY_SCOPES_RATINGFILTER_H |
567 | +#define UNITY_SCOPES_RATINGFILTER_H |
568 | + |
569 | +#include <unity/scopes/FilterBase.h> |
570 | +#include <unity/scopes/FilterOption.h> |
571 | + |
572 | +namespace unity |
573 | +{ |
574 | + |
575 | +namespace scopes |
576 | +{ |
577 | + |
578 | +class FilterState; |
579 | + |
580 | +namespace internal |
581 | +{ |
582 | + |
583 | +class RatingFilterImpl; |
584 | + |
585 | +} |
586 | + |
587 | +/** |
588 | +\brief A filter that allows for rating-based selection. |
589 | + |
590 | +Displays filter with a set of options, where every option has a label and icon. |
591 | +Only one option can be active at a time. The active option uses the icon in "on" state |
592 | +(see unity::scopes::RatingFilter::set_on_icon() ). All other icons are "off" (see unity::scopes::RatingFilter::set_off_icon() ). |
593 | +By default, "on" and "off" icons are bright and dim star respectively. |
594 | + |
595 | +This filter is best suited for rating-based filtering. |
596 | +*/ |
597 | +class UNITY_API RatingFilter : public FilterBase |
598 | +{ |
599 | +public: |
600 | +/// @cond |
601 | + UNITY_DEFINES_PTRS(RatingFilter); |
602 | +/// @endcond |
603 | + |
604 | + /** |
605 | + \brief Creates RatingFilter widget. |
606 | + |
607 | + Creates an empty RatingFilter widget. Use unity::scopes::RatingFilter::add_option() to add rating options to it. |
608 | + \param id A unique identifier for the filter that can be used to identify it later among several filters. |
609 | + \param label A display label for this filter |
610 | + \return Instance of RatingFilter |
611 | + */ |
612 | + static RatingFilter::UPtr create(std::string const& id, std::string const& label); |
613 | + |
614 | + /** |
615 | + \brief Creates RatingFilter widget. |
616 | + |
617 | + Creates a RatingFilter widget and populates it with some standard rating options. |
618 | + This is a convienience factory method, that fills RatingFilter in with options for ratings |
619 | + from 1 up to top_rating. Options are created with identifiers "1", "2" and so on, and labels |
620 | + "1+", "2+" etc., except for that last label, which is just the number (no plus sign). The maximum top_rating |
621 | + allowed is 10. |
622 | + |
623 | + \param id A unique identifier for the filter that can be used to identify it later among several filters. |
624 | + \param label A display label for this filter |
625 | + \param top_rating The maximum rating allowed. |
626 | + \return Instance of RatingFilter |
627 | + */ |
628 | + static RatingFilter::UPtr create(std::string const& id, std::string const& label, int top_rating); |
629 | + |
630 | + /** |
631 | + \brief Adds a new option to the filter. |
632 | + |
633 | + \param id A unique identifier of the option. |
634 | + \param label A display label for the option |
635 | + \return Instance of FilterOption |
636 | + */ |
637 | + FilterOption::SCPtr add_option(std::string const& id, std::string const& label); |
638 | + |
639 | + /** |
640 | + \brief Set a custom icon for the "on" state. |
641 | + |
642 | + If not set, a star icon will be used by default. |
643 | + |
644 | + \param on_icon icon uri |
645 | + */ |
646 | + void set_on_icon(std::string const& on_icon); |
647 | + |
648 | + /** |
649 | + \brief Set a custom icon for the "off" state. |
650 | + |
651 | + If not set, a dim star icon will be used by default. |
652 | + |
653 | + \param off_icon icon uri |
654 | + */ |
655 | + void set_off_icon(std::string const& off_icon); |
656 | + |
657 | + /** |
658 | + \brief Get the label of this filter. |
659 | + \return The filter label. |
660 | + */ |
661 | + std::string label() const; |
662 | + |
663 | + /** |
664 | + \brief Get custom icon for the "on" state. |
665 | + |
666 | + If empty, then the default icon will be used. |
667 | + |
668 | + \return icon uri or empty string |
669 | + */ |
670 | + std::string on_icon() const; |
671 | + |
672 | + /** |
673 | + \brief Get custom icon for the "off" state. |
674 | + |
675 | + If empty, then the default icon will be used. |
676 | + |
677 | + \return icon uri or empty string |
678 | + */ |
679 | + std::string off_icon() const; |
680 | + |
681 | + /** |
682 | + \brief Get all options of this filter, in the order they were added. |
683 | + \return The list of options. |
684 | + */ |
685 | + std::list<FilterOption::SCPtr> options() const; |
686 | + |
687 | + /** |
688 | + \brief Check if a rating option is active. |
689 | + \param filter_state The state of filters |
690 | + \return true if a rating option is active. |
691 | + */ |
692 | + bool has_active_rating(FilterState const& filter_state) const; |
693 | + |
694 | + /** |
695 | + \brief Get active option from an instance of FilterState for this filter. |
696 | + \return The active option or nullptr if no option is active. |
697 | + */ |
698 | + FilterOption::SCPtr active_rating(FilterState const& filter_state) const; |
699 | + |
700 | + /** |
701 | + \brief Marks given FilterOption of this filter instance as active (or not active) in a FilterState object. |
702 | + |
703 | + Records the given FilterOption as "selected" in the FilterState. This is meant to be used to modify a |
704 | + FilterState received with a search request before sending it back to the client (UI shell). |
705 | + Only one option can be active at a time - marking an option active automatically deactivates any other option. |
706 | + */ |
707 | + void update_state(FilterState& filter_state, FilterOption::SCPtr option, bool active) const; |
708 | + |
709 | + /** |
710 | + \brief Marks an option of a filter active/inactive in a FilterState object, without having an instance of OptionSelectorFilter. |
711 | + |
712 | + Updates an instance of FilterState, without the need for an OptionSelectorFilter instance. This is meant |
713 | + to be used when creating a canned Query that references another scope. |
714 | + */ |
715 | + static void update_state(FilterState& filter_state, std::string const& filter_id, std::string const& option_id, bool value); |
716 | + |
717 | +private: |
718 | + RatingFilter(internal::RatingFilterImpl*); |
719 | + internal::RatingFilterImpl* fwd() const; |
720 | + friend class internal::RatingFilterImpl; |
721 | +}; |
722 | + |
723 | +} // namespace scopes |
724 | + |
725 | +} // namespace unity |
726 | + |
727 | +#endif |
728 | |
729 | === modified file 'include/unity/scopes/internal/FilterBaseImpl.h' |
730 | --- include/unity/scopes/internal/FilterBaseImpl.h 2014-05-02 10:19:46 +0000 |
731 | +++ include/unity/scopes/internal/FilterBaseImpl.h 2014-05-21 14:02:43 +0000 |
732 | @@ -47,6 +47,7 @@ |
733 | static FilterBase::SCPtr deserialize(VariantMap const& var); |
734 | static VariantArray serialize_filters(Filters const& filters); |
735 | static Filters deserialize_filters(VariantArray const& var); |
736 | + static void validate_filters(Filters const& filters); |
737 | |
738 | protected: |
739 | virtual void serialize(VariantMap& var) const = 0; |
740 | |
741 | === added file 'include/unity/scopes/internal/MWPublisher.h' |
742 | --- include/unity/scopes/internal/MWPublisher.h 1970-01-01 00:00:00 +0000 |
743 | +++ include/unity/scopes/internal/MWPublisher.h 2014-05-21 14:02:43 +0000 |
744 | @@ -0,0 +1,55 @@ |
745 | +/* |
746 | + * Copyright (C) 2014 Canonical Ltd |
747 | + * |
748 | + * This program is free software: you can redistribute it and/or modify |
749 | + * it under the terms of the GNU Lesser General Public License version 3 as |
750 | + * published by the Free Software Foundation. |
751 | + * |
752 | + * This program is distributed in the hope that it will be useful, |
753 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
754 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
755 | + * GNU Lesser General Public License for more details. |
756 | + * |
757 | + * You should have received a copy of the GNU Lesser General Public License |
758 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
759 | + * |
760 | + * Authored by: Marcus Tomlinson <marcus.tomlinson@canonical.com> |
761 | + */ |
762 | + |
763 | +#ifndef UNITY_SCOPES_INTERNAL_MWPUBLISHER_H |
764 | +#define UNITY_SCOPES_INTERNAL_MWPUBLISHER_H |
765 | + |
766 | +#include <unity/util/DefinesPtrs.h> |
767 | +#include <unity/util/NonCopyable.h> |
768 | + |
769 | +namespace unity |
770 | +{ |
771 | + |
772 | +namespace scopes |
773 | +{ |
774 | + |
775 | +namespace internal |
776 | +{ |
777 | + |
778 | +class MWPublisher |
779 | +{ |
780 | +public: |
781 | + NONCOPYABLE(MWPublisher); |
782 | + UNITY_DEFINES_PTRS(MWPublisher); |
783 | + |
784 | + virtual ~MWPublisher(); |
785 | + |
786 | + virtual std::string endpoint() const = 0; |
787 | + virtual void send_message(std::string const& message, std::string const& topic = "") = 0; |
788 | + |
789 | +protected: |
790 | + MWPublisher(); |
791 | +}; |
792 | + |
793 | +} // namespace internal |
794 | + |
795 | +} // namespace scopes |
796 | + |
797 | +} // namespace unity |
798 | + |
799 | +#endif // UNITY_SCOPES_INTERNAL_MWPUBLISHER_H |
800 | |
801 | === added file 'include/unity/scopes/internal/MWSubscriber.h' |
802 | --- include/unity/scopes/internal/MWSubscriber.h 1970-01-01 00:00:00 +0000 |
803 | +++ include/unity/scopes/internal/MWSubscriber.h 2014-05-21 14:02:43 +0000 |
804 | @@ -0,0 +1,57 @@ |
805 | +/* |
806 | + * Copyright (C) 2014 Canonical Ltd |
807 | + * |
808 | + * This program is free software: you can redistribute it and/or modify |
809 | + * it under the terms of the GNU Lesser General Public License version 3 as |
810 | + * published by the Free Software Foundation. |
811 | + * |
812 | + * This program is distributed in the hope that it will be useful, |
813 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
814 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
815 | + * GNU Lesser General Public License for more details. |
816 | + * |
817 | + * You should have received a copy of the GNU Lesser General Public License |
818 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
819 | + * |
820 | + * Authored by: Marcus Tomlinson <marcus.tomlinson@canonical.com> |
821 | + */ |
822 | + |
823 | +#ifndef UNITY_SCOPES_INTERNAL_MWSUBSCRIBER_H |
824 | +#define UNITY_SCOPES_INTERNAL_MWSUBSCRIBER_H |
825 | + |
826 | +#include <unity/util/DefinesPtrs.h> |
827 | +#include <unity/util/NonCopyable.h> |
828 | + |
829 | +namespace unity |
830 | +{ |
831 | + |
832 | +namespace scopes |
833 | +{ |
834 | + |
835 | +namespace internal |
836 | +{ |
837 | + |
838 | +typedef std::function<void(std::string const& message)> SubscriberCallback; |
839 | + |
840 | +class MWSubscriber |
841 | +{ |
842 | +public: |
843 | + NONCOPYABLE(MWSubscriber); |
844 | + UNITY_DEFINES_PTRS(MWSubscriber); |
845 | + |
846 | + virtual ~MWSubscriber(); |
847 | + |
848 | + virtual std::string endpoint() const = 0; |
849 | + virtual void set_message_callback(SubscriberCallback callback) = 0; |
850 | + |
851 | +protected: |
852 | + MWSubscriber(); |
853 | +}; |
854 | + |
855 | +} // namespace internal |
856 | + |
857 | +} // namespace scopes |
858 | + |
859 | +} // namespace unity |
860 | + |
861 | +#endif // UNITY_SCOPES_INTERNAL_MWSUBSCRIBER_H |
862 | |
863 | === modified file 'include/unity/scopes/internal/MiddlewareBase.h' |
864 | --- include/unity/scopes/internal/MiddlewareBase.h 2014-05-08 12:55:26 +0000 |
865 | +++ include/unity/scopes/internal/MiddlewareBase.h 2014-05-21 14:02:43 +0000 |
866 | @@ -20,11 +20,13 @@ |
867 | #define UNITY_SCOPES_INTERNAL_MIDDLEWAREBASE_H |
868 | |
869 | #include <unity/scopes/internal/MWObjectProxyFwd.h> |
870 | +#include <unity/scopes/internal/MWPublisher.h> |
871 | #include <unity/scopes/internal/MWQueryCtrlProxyFwd.h> |
872 | #include <unity/scopes/internal/MWQueryProxyFwd.h> |
873 | #include <unity/scopes/internal/MWRegistryProxyFwd.h> |
874 | #include <unity/scopes/internal/MWScopeProxyFwd.h> |
875 | #include <unity/scopes/internal/MWStateReceiverProxyFwd.h> |
876 | +#include <unity/scopes/internal/MWSubscriber.h> |
877 | #include <unity/scopes/internal/QueryObjectBase.h> |
878 | #include <unity/scopes/internal/QueryCtrlObjectBase.h> |
879 | #include <unity/scopes/internal/RegistryObjectBase.h> |
880 | @@ -84,6 +86,9 @@ |
881 | virtual void add_dflt_scope_object(ScopeObjectBase::SPtr const& scope) = 0; |
882 | virtual MWStateReceiverProxy add_state_receiver_object(std::string const& identity, StateReceiverObject::SPtr const& state_receiver) = 0; |
883 | |
884 | + virtual MWPublisher::UPtr create_publisher(std::string const& publisher_id) = 0; |
885 | + virtual MWSubscriber::UPtr create_subscriber(std::string const& publisher_id, std::string const& topic = "") = 0; |
886 | + |
887 | virtual std::string get_scope_endpoint() = 0; |
888 | virtual std::string get_query_endpoint() = 0; |
889 | virtual std::string get_query_ctrl_endpoint() = 0; |
890 | |
891 | === modified file 'include/unity/scopes/internal/OptionSelectorFilterImpl.h' |
892 | --- include/unity/scopes/internal/OptionSelectorFilterImpl.h 2014-05-08 16:10:18 +0000 |
893 | +++ include/unity/scopes/internal/OptionSelectorFilterImpl.h 2014-05-21 14:02:43 +0000 |
894 | @@ -43,9 +43,11 @@ |
895 | OptionSelectorFilterImpl(VariantMap const& var); |
896 | std::string label() const; |
897 | bool multi_select() const; |
898 | - FilterOption::SCPtr add_option(std::string const& id, std::string const& label); |
899 | + virtual FilterOption::SCPtr add_option(std::string const& id, std::string const& label); |
900 | std::list<FilterOption::SCPtr> options() const; |
901 | + int num_of_options() const; |
902 | std::set<FilterOption::SCPtr> active_options(FilterState const& filter_state) const; |
903 | + bool has_active_option(FilterState const& filter_state) const; |
904 | void update_state(FilterState& filter_state, FilterOption::SCPtr option, bool active) const; |
905 | static void update_state(FilterState& filter_state, std::string const& filter_id, std::string const& option_id, bool value); |
906 | static OptionSelectorFilter::SPtr create(VariantMap const& var); |
907 | |
908 | === added file 'include/unity/scopes/internal/RadioButtonsFilterImpl.h' |
909 | --- include/unity/scopes/internal/RadioButtonsFilterImpl.h 1970-01-01 00:00:00 +0000 |
910 | +++ include/unity/scopes/internal/RadioButtonsFilterImpl.h 2014-05-21 14:02:43 +0000 |
911 | @@ -0,0 +1,50 @@ |
912 | +/* |
913 | + * Copyright (C) 2014 Canonical Ltd |
914 | + * |
915 | + * This program is free software: you can redistribute it and/or modify |
916 | + * it under the terms of the GNU Lesser General Public License version 3 as |
917 | + * published by the Free Software Foundation. |
918 | + * |
919 | + * This program is distributed in the hope that it will be useful, |
920 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
921 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
922 | + * GNU Lesser General Public License for more details. |
923 | + * |
924 | + * You should have received a copy of the GNU Lesser General Public License |
925 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
926 | + * |
927 | + * Authored by: Pawel Stolowski <pawel.stolowski@canonical.com> |
928 | + */ |
929 | + |
930 | +#ifndef UNITY_INTERNAL_RADIOBUTTONSFILTERIMPL_H |
931 | +#define UNITY_INTERNAL_RADIOBUTTONSFILTERIMPL_H |
932 | + |
933 | +#include <unity/scopes/internal/OptionSelectorFilterImpl.h> |
934 | +#include <unity/scopes/RadioButtonsFilter.h> |
935 | + |
936 | +namespace unity |
937 | +{ |
938 | + |
939 | +namespace scopes |
940 | +{ |
941 | + |
942 | +namespace internal |
943 | +{ |
944 | + |
945 | +class RadioButtonsFilterImpl : public OptionSelectorFilterImpl |
946 | +{ |
947 | +public: |
948 | + RadioButtonsFilterImpl(std::string const& id, std::string const& label); |
949 | + RadioButtonsFilterImpl(VariantMap const& var); |
950 | + FilterOption::SCPtr active_option(FilterState const& filter_state) const; |
951 | + std::string filter_type() const override; |
952 | + static RadioButtonsFilter::SPtr create(VariantMap const& var); |
953 | +}; |
954 | + |
955 | +} // namespace internal |
956 | + |
957 | +} // namespace scopes |
958 | + |
959 | +} // namespace unity |
960 | + |
961 | +#endif |
962 | |
963 | === added file 'include/unity/scopes/internal/RatingFilterImpl.h' |
964 | --- include/unity/scopes/internal/RatingFilterImpl.h 1970-01-01 00:00:00 +0000 |
965 | +++ include/unity/scopes/internal/RatingFilterImpl.h 2014-05-21 14:02:43 +0000 |
966 | @@ -0,0 +1,64 @@ |
967 | +/* |
968 | + * Copyright (C) 2014 Canonical Ltd |
969 | + * |
970 | + * This program is free software: you can redistribute it and/or modify |
971 | + * it under the terms of the GNU Lesser General Public License version 3 as |
972 | + * published by the Free Software Foundation. |
973 | + * |
974 | + * This program is distributed in the hope that it will be useful, |
975 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
976 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
977 | + * GNU Lesser General Public License for more details. |
978 | + * |
979 | + * You should have received a copy of the GNU Lesser General Public License |
980 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
981 | + * |
982 | + * Authored by: Pawel Stolowski <pawel.stolowski@canonical.com> |
983 | + */ |
984 | + |
985 | +#ifndef UNITY_INTERNAL_RATINGFILTERIMPL_H |
986 | +#define UNITY_INTERNAL_RATINGFILTERIMPL_H |
987 | + |
988 | +#include <unity/scopes/internal/RadioButtonsFilterImpl.h> |
989 | +#include <unity/scopes/RatingFilter.h> |
990 | + |
991 | +namespace unity |
992 | +{ |
993 | + |
994 | +namespace scopes |
995 | +{ |
996 | + |
997 | +namespace internal |
998 | +{ |
999 | + |
1000 | +class RatingFilterImpl : public RadioButtonsFilterImpl |
1001 | +{ |
1002 | +public: |
1003 | + RatingFilterImpl(std::string const& id, std::string const& label); |
1004 | + RatingFilterImpl(std::string const& id, std::string const& label, int top_rating); |
1005 | + RatingFilterImpl(VariantMap const& var); |
1006 | + FilterOption::SCPtr add_option(std::string const& id, std::string const& label) override; |
1007 | + void set_on_icon(std::string const& on_icon); |
1008 | + void set_off_icon(std::string const& off_icon); |
1009 | + std::string on_icon() const; |
1010 | + std::string off_icon() const; |
1011 | + FilterOption::SCPtr active_rating(FilterState const& filter_state) const; |
1012 | + |
1013 | + static RatingFilter::SPtr create(VariantMap const& var); |
1014 | + |
1015 | + std::string filter_type() const override; |
1016 | + |
1017 | + static const int max_rating = 10; |
1018 | + |
1019 | +private: |
1020 | + std::string on_icon_; |
1021 | + std::string off_icon_; |
1022 | +}; |
1023 | + |
1024 | +} // namespace internal |
1025 | + |
1026 | +} // namespace scopes |
1027 | + |
1028 | +} // namespace unity |
1029 | + |
1030 | +#endif |
1031 | |
1032 | === modified file 'include/unity/scopes/internal/smartscopes/SmartScopesClient.h' |
1033 | --- include/unity/scopes/internal/smartscopes/SmartScopesClient.h 2014-03-24 10:15:20 +0000 |
1034 | +++ include/unity/scopes/internal/smartscopes/SmartScopesClient.h 2014-05-21 14:02:43 +0000 |
1035 | @@ -54,6 +54,7 @@ |
1036 | std::string base_url; |
1037 | std::shared_ptr<std::string> icon; // optional |
1038 | std::shared_ptr<std::string> art; // optional |
1039 | + std::shared_ptr<VariantMap> appearance; // optional |
1040 | bool invisible = false; |
1041 | }; |
1042 | |
1043 | |
1044 | === modified file 'include/unity/scopes/internal/zmq_middleware/ObjectAdapter.h' |
1045 | --- include/unity/scopes/internal/zmq_middleware/ObjectAdapter.h 2014-05-08 13:27:38 +0000 |
1046 | +++ include/unity/scopes/internal/zmq_middleware/ObjectAdapter.h 2014-05-21 14:02:43 +0000 |
1047 | @@ -98,8 +98,6 @@ |
1048 | // zmqpp::socket subscribe_to_ctrl_socket(); |
1049 | // void stop_workers() noexcept; |
1050 | |
1051 | - void safe_bind(zmqpp::socket& s, std::string const& endpoint); |
1052 | - |
1053 | std::shared_ptr<ServantBase> find_servant(std::string const& id, std::string const& category); |
1054 | |
1055 | // Thread start functions |
1056 | |
1057 | === modified file 'include/unity/scopes/internal/zmq_middleware/Util.h' |
1058 | --- include/unity/scopes/internal/zmq_middleware/Util.h 2014-01-28 06:34:03 +0000 |
1059 | +++ include/unity/scopes/internal/zmq_middleware/Util.h 2014-05-21 14:02:43 +0000 |
1060 | @@ -19,6 +19,8 @@ |
1061 | #ifndef UNITY_SCOPES_INTERNAL_ZMQMIDDLEWARE_UTIL_H |
1062 | #define UNITY_SCOPES_INTERNAL_ZMQMIDDLEWARE_UTIL_H |
1063 | |
1064 | +#include <zmqpp/socket.hpp> |
1065 | + |
1066 | #include <string> |
1067 | |
1068 | namespace unity |
1069 | @@ -35,6 +37,8 @@ |
1070 | |
1071 | void throw_if_bad_endpoint(std::string const& endpoint); |
1072 | |
1073 | +void safe_bind(zmqpp::socket& s, std::string const& endpoint); |
1074 | + |
1075 | } // namespace zmq_middleware |
1076 | |
1077 | } // namespace internal |
1078 | |
1079 | === modified file 'include/unity/scopes/internal/zmq_middleware/ZmqMiddleware.h' |
1080 | --- include/unity/scopes/internal/zmq_middleware/ZmqMiddleware.h 2014-05-15 00:34:39 +0000 |
1081 | +++ include/unity/scopes/internal/zmq_middleware/ZmqMiddleware.h 2014-05-21 14:02:43 +0000 |
1082 | @@ -78,10 +78,13 @@ |
1083 | virtual void add_dflt_query_object(QueryObjectBase::SPtr const& query) override; |
1084 | virtual MWRegistryProxy add_registry_object(std::string const& identity, RegistryObjectBase::SPtr const& registry) override; |
1085 | virtual MWReplyProxy add_reply_object(ReplyObjectBase::SPtr const& reply) override; |
1086 | - virtual MWScopeProxy add_scope_object(std::string const& identity, ScopeObjectBase::SPtr const& scope, int64_t idle_timeout = 0) override; |
1087 | + virtual MWScopeProxy add_scope_object(std::string const& identity, ScopeObjectBase::SPtr const& scope, int64_t idle_timeout) override; |
1088 | virtual void add_dflt_scope_object(ScopeObjectBase::SPtr const& scope) override; |
1089 | virtual MWStateReceiverProxy add_state_receiver_object(std::string const& identity, StateReceiverObject::SPtr const& state_receiver) override; |
1090 | |
1091 | + virtual MWPublisher::UPtr create_publisher(std::string const& publisher_id) override; |
1092 | + virtual MWSubscriber::UPtr create_subscriber(std::string const& publisher_id, std::string const& topic) override; |
1093 | + |
1094 | virtual std::string get_scope_endpoint() override; |
1095 | virtual std::string get_query_endpoint() override; |
1096 | virtual std::string get_query_ctrl_endpoint() override; |
1097 | |
1098 | === added file 'include/unity/scopes/internal/zmq_middleware/ZmqPublisher.h' |
1099 | --- include/unity/scopes/internal/zmq_middleware/ZmqPublisher.h 1970-01-01 00:00:00 +0000 |
1100 | +++ include/unity/scopes/internal/zmq_middleware/ZmqPublisher.h 2014-05-21 14:02:43 +0000 |
1101 | @@ -0,0 +1,83 @@ |
1102 | +/* |
1103 | + * Copyright (C) 2014 Canonical Ltd |
1104 | + * |
1105 | + * This program is free software: you can redistribute it and/or modify |
1106 | + * it under the terms of the GNU Lesser General Public License version 3 as |
1107 | + * published by the Free Software Foundation. |
1108 | + * |
1109 | + * This program is distributed in the hope that it will be useful, |
1110 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1111 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1112 | + * GNU Lesser General Public License for more details. |
1113 | + * |
1114 | + * You should have received a copy of the GNU Lesser General Public License |
1115 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1116 | + * |
1117 | + * Authored by: Marcus Tomlinson <marcus.tomlinson@canonical.com> |
1118 | + */ |
1119 | + |
1120 | +#ifndef UNITY_SCOPES_INTERNAL_ZMQMIDDLEWARE_ZMQPUBLISHER_H |
1121 | +#define UNITY_SCOPES_INTERNAL_ZMQMIDDLEWARE_ZMQPUBLISHER_H |
1122 | + |
1123 | +#include <unity/scopes/internal/MWPublisher.h> |
1124 | + |
1125 | +#include <zmqpp/context.hpp> |
1126 | +#include <zmqpp/socket.hpp> |
1127 | + |
1128 | +#include <condition_variable> |
1129 | +#include <queue> |
1130 | +#include <thread> |
1131 | + |
1132 | +namespace unity |
1133 | +{ |
1134 | + |
1135 | +namespace scopes |
1136 | +{ |
1137 | + |
1138 | +namespace internal |
1139 | +{ |
1140 | + |
1141 | +namespace zmq_middleware |
1142 | +{ |
1143 | + |
1144 | +class ZmqPublisher : public virtual MWPublisher |
1145 | +{ |
1146 | +public: |
1147 | + ZmqPublisher(zmqpp::context* context, std::string const& publisher_id, |
1148 | + std::string const& endpoint_dir); |
1149 | + virtual ~ZmqPublisher(); |
1150 | + |
1151 | + std::string endpoint() const override; |
1152 | + void send_message(std::string const& message, std::string const& topic) override; |
1153 | + |
1154 | +private: |
1155 | + enum ThreadState |
1156 | + { |
1157 | + NotRunning, |
1158 | + Running, |
1159 | + Stopping, |
1160 | + Failed |
1161 | + }; |
1162 | + |
1163 | + zmqpp::context* const context_; |
1164 | + std::string const endpoint_; |
1165 | + std::queue<std::string> message_queue_; |
1166 | + |
1167 | + std::thread thread_; |
1168 | + std::mutex mutex_; |
1169 | + std::condition_variable cond_; |
1170 | + ThreadState thread_state_; |
1171 | + std::exception_ptr thread_exception_; |
1172 | + |
1173 | + void publisher_thread(); |
1174 | +}; |
1175 | + |
1176 | +} // namespace zmq_middleware |
1177 | + |
1178 | +} // namespace internal |
1179 | + |
1180 | +} // namespace scopes |
1181 | + |
1182 | +} // namespace unity |
1183 | + |
1184 | +#endif // UNITY_SCOPES_INTERNAL_ZMQMIDDLEWARE_ZMQPUBLISHER_H |
1185 | |
1186 | === added file 'include/unity/scopes/internal/zmq_middleware/ZmqSubscriber.h' |
1187 | --- include/unity/scopes/internal/zmq_middleware/ZmqSubscriber.h 1970-01-01 00:00:00 +0000 |
1188 | +++ include/unity/scopes/internal/zmq_middleware/ZmqSubscriber.h 2014-05-21 14:02:43 +0000 |
1189 | @@ -0,0 +1,86 @@ |
1190 | +/* |
1191 | + * Copyright (C) 2014 Canonical Ltd |
1192 | + * |
1193 | + * This program is free software: you can redistribute it and/or modify |
1194 | + * it under the terms of the GNU Lesser General Public License version 3 as |
1195 | + * published by the Free Software Foundation. |
1196 | + * |
1197 | + * This program is distributed in the hope that it will be useful, |
1198 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1199 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1200 | + * GNU Lesser General Public License for more details. |
1201 | + * |
1202 | + * You should have received a copy of the GNU Lesser General Public License |
1203 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1204 | + * |
1205 | + * Authored by: Marcus Tomlinson <marcus.tomlinson@canonical.com> |
1206 | + */ |
1207 | + |
1208 | +#ifndef UNITY_SCOPES_INTERNAL_ZMQMIDDLEWARE_ZMQSUBSCRIBER_H |
1209 | +#define UNITY_SCOPES_INTERNAL_ZMQMIDDLEWARE_ZMQSUBSCRIBER_H |
1210 | + |
1211 | +#include <unity/scopes/internal/MWSubscriber.h> |
1212 | + |
1213 | +#include <zmqpp/context.hpp> |
1214 | + |
1215 | +#include <condition_variable> |
1216 | +#include <thread> |
1217 | + |
1218 | +namespace unity |
1219 | +{ |
1220 | + |
1221 | +namespace scopes |
1222 | +{ |
1223 | + |
1224 | +namespace internal |
1225 | +{ |
1226 | + |
1227 | +namespace zmq_middleware |
1228 | +{ |
1229 | + |
1230 | +class StopPublisher; |
1231 | + |
1232 | +class ZmqSubscriber : public virtual MWSubscriber |
1233 | +{ |
1234 | +public: |
1235 | + ZmqSubscriber(zmqpp::context* context, std::string const& publisher_id, |
1236 | + std::string const& endpoint_dir, std::string const& topic); |
1237 | + virtual ~ZmqSubscriber(); |
1238 | + |
1239 | + std::string endpoint() const override; |
1240 | + void set_message_callback(SubscriberCallback callback) override; |
1241 | + |
1242 | +private: |
1243 | + enum ThreadState |
1244 | + { |
1245 | + NotRunning, |
1246 | + Running, |
1247 | + Stopping, |
1248 | + Failed |
1249 | + }; |
1250 | + |
1251 | + zmqpp::context* const context_; |
1252 | + std::string const endpoint_; |
1253 | + std::string const topic_; |
1254 | + |
1255 | + std::thread thread_; |
1256 | + std::unique_ptr<StopPublisher> thread_stopper_; |
1257 | + std::mutex mutex_; |
1258 | + std::condition_variable cond_; |
1259 | + ThreadState thread_state_; |
1260 | + std::exception_ptr thread_exception_; |
1261 | + |
1262 | + SubscriberCallback callback_; |
1263 | + |
1264 | + void subscriber_thread(); |
1265 | +}; |
1266 | + |
1267 | +} // namespace zmq_middleware |
1268 | + |
1269 | +} // namespace internal |
1270 | + |
1271 | +} // namespace scopes |
1272 | + |
1273 | +} // namespace unity |
1274 | + |
1275 | +#endif // UNITY_SCOPES_INTERNAL_ZMQMIDDLEWARE_ZMQSUBSCRIBER_H |
1276 | |
1277 | === modified file 'scoperegistry/CMakeLists.txt' |
1278 | --- scoperegistry/CMakeLists.txt 2014-05-06 09:00:45 +0000 |
1279 | +++ scoperegistry/CMakeLists.txt 2014-05-21 14:02:43 +0000 |
1280 | @@ -1,7 +1,6 @@ |
1281 | set(SRC |
1282 | FindFiles.cpp |
1283 | scoperegistry.cpp |
1284 | - ScopeSet.cpp |
1285 | ) |
1286 | |
1287 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}) |
1288 | |
1289 | === modified file 'scoperegistry/FindFiles.cpp' |
1290 | --- scoperegistry/FindFiles.cpp 2014-04-04 13:22:38 +0000 |
1291 | +++ scoperegistry/FindFiles.cpp 2014-05-21 14:02:43 +0000 |
1292 | @@ -21,12 +21,14 @@ |
1293 | #include <unity/UnityExceptions.h> |
1294 | #include <unity/util/ResourcePtr.h> |
1295 | |
1296 | +#include <boost/filesystem/path.hpp> |
1297 | + |
1298 | +#include <map> |
1299 | + |
1300 | #include <dirent.h> |
1301 | #include <string.h> |
1302 | #include <sys/stat.h> |
1303 | |
1304 | -#include <boost/filesystem/path.hpp> |
1305 | - |
1306 | using namespace std; |
1307 | using namespace unity; |
1308 | using namespace boost; |
1309 | @@ -86,10 +88,14 @@ |
1310 | // Return all files of the form dir/*/<scomescope>.ini that are regular files or |
1311 | // symbolic links and have the specified suffix. |
1312 | // The empty suffix is legal and causes all regular files and symlinks to be returned. |
1313 | +// Print error message for any scopes with an id that was seen previously. |
1314 | |
1315 | -vector<string> find_scope_config_files(string const& install_dir, string const& suffix) |
1316 | +vector<string> find_scope_config_files(string const& install_dir, |
1317 | + string const& suffix, |
1318 | + function<void(string const&)> error) |
1319 | { |
1320 | vector<string> files; |
1321 | + map<string, string> scopes_seen; |
1322 | |
1323 | auto subdirs = find_entries(install_dir, Directory); |
1324 | for (auto subdir : subdirs) |
1325 | @@ -97,13 +103,18 @@ |
1326 | auto candidates = find_entries(subdir, File); |
1327 | for (auto c : candidates) |
1328 | { |
1329 | - // TODO Check for multiple ini files |
1330 | - |
1331 | filesystem::path path(c); |
1332 | if (path.extension() != suffix) { |
1333 | continue; |
1334 | } |
1335 | - |
1336 | + auto stem = path.stem().native(); |
1337 | + auto const it = scopes_seen.find(stem); |
1338 | + if (it != scopes_seen.end()) |
1339 | + { |
1340 | + error("ignoring second instance of non-unique scope: " + path.native() + "\n" |
1341 | + "previous instance: " + it->second); |
1342 | + } |
1343 | + scopes_seen[stem] = path.native(); |
1344 | files.emplace_back(c); |
1345 | } |
1346 | } |
1347 | |
1348 | === modified file 'scoperegistry/FindFiles.h' |
1349 | --- scoperegistry/FindFiles.h 2013-11-21 21:44:00 +0000 |
1350 | +++ scoperegistry/FindFiles.h 2014-05-21 14:02:43 +0000 |
1351 | @@ -19,8 +19,9 @@ |
1352 | #ifndef SCOPEREGISTRY_FINDFILES_H |
1353 | #define SCOPEREGISTRY_FINDFILES_H |
1354 | |
1355 | +#include <functional> |
1356 | +#include <string> |
1357 | #include <vector> |
1358 | -#include <string> |
1359 | |
1360 | namespace scoperegistry |
1361 | { |
1362 | @@ -34,11 +35,14 @@ |
1363 | // we get those two .ini files, but no .ini files in canonical or underneath |
1364 | // further-nested directories. |
1365 | |
1366 | -std::vector<std::string> find_scope_config_files(std::string const& install_dir, std::string const& suffix); |
1367 | +std::vector<std::string> find_scope_config_files(std::string const& install_dir, |
1368 | + std::string const& suffix, |
1369 | + std::function<void(std::string const&)> error); |
1370 | |
1371 | // Return a vector of file names in dir with the given suffix. |
1372 | |
1373 | -std::vector<std::string> find_files(std::string const& dir, std::string const& suffix); |
1374 | +std::vector<std::string> find_files(std::string const& dir, |
1375 | + std::string const& suffix); |
1376 | |
1377 | } // namespace scoperegistry |
1378 | |
1379 | |
1380 | === removed file 'scoperegistry/ScopeSet.cpp' |
1381 | --- scoperegistry/ScopeSet.cpp 2014-04-03 12:57:25 +0000 |
1382 | +++ scoperegistry/ScopeSet.cpp 1970-01-01 00:00:00 +0000 |
1383 | @@ -1,124 +0,0 @@ |
1384 | -/* |
1385 | - * Copyright (C) 2013 Canonical Ltd |
1386 | - * |
1387 | - * This program is free software: you can redistribute it and/or modify |
1388 | - * it under the terms of the Lesser GNU General Public License version 3 as |
1389 | - * published by the Free Software Foundation. |
1390 | - * |
1391 | - * This program is distributed in the hope that it will be useful, |
1392 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1393 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1394 | - * GNU Lesser General Public License for more details. |
1395 | - * |
1396 | - * You should have received a copy of the GNU Lesser General Public License |
1397 | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1398 | - * |
1399 | - * Authored by: Jussi Pakkanen <jussi.pakkanen@canonical.com> |
1400 | - */ |
1401 | - |
1402 | -#include"FindFiles.h" |
1403 | -#include"ScopeSet.h" |
1404 | -#include <unity/scopes/ScopeMetadata.h> |
1405 | -#include <unity/scopes/internal/RegistryConfig.h> |
1406 | -#include <unity/scopes/internal/ScopeConfig.h> |
1407 | -#include <unity/scopes/ScopeExceptions.h> |
1408 | -#include<memory> |
1409 | -#include<map> |
1410 | -#include<set> |
1411 | -#include<cstring> |
1412 | - |
1413 | -using namespace std; |
1414 | -using namespace unity::scopes; |
1415 | -using namespace unity::scopes::internal; |
1416 | - |
1417 | -namespace scoperegistry |
1418 | -{ |
1419 | - |
1420 | -static string strip_suffix(string const& s, string const& suffix) |
1421 | -{ |
1422 | - auto s_len = s.length(); |
1423 | - auto suffix_len = suffix.length(); |
1424 | - if (s_len >= suffix_len) |
1425 | - { |
1426 | - if (s.compare(s_len - suffix_len, suffix_len, suffix) == 0) |
1427 | - { |
1428 | - return string(s, 0, s_len - suffix_len); |
1429 | - } |
1430 | - } |
1431 | - return s; |
1432 | -} |
1433 | - |
1434 | -struct ScopeSetPrivate |
1435 | -{ |
1436 | - std::set<string> overridable_scopes; |
1437 | - std::map<string, unique_ptr<ScopeConfig>> scopes; |
1438 | -}; |
1439 | - |
1440 | -ScopeSet::ScopeSet(const RegistryConfig& c) : p(new ScopeSetPrivate()) |
1441 | -{ |
1442 | - string canonical_dir = c.scope_installdir(); |
1443 | - string oem_dir = c.oem_installdir(); |
1444 | - auto canonical_files = find_scope_config_files(canonical_dir, ".ini"); |
1445 | - auto oem_files = find_scope_config_files(oem_dir, ".ini"); |
1446 | - for (const auto &path : canonical_files) |
1447 | - { |
1448 | - unique_ptr<ScopeConfig> sc(new ScopeConfig(path)); |
1449 | - // basename() modifies its argument |
1450 | - string file_name = basename(const_cast<char*>(string(path).c_str())); |
1451 | - string scope_id = strip_suffix(file_name, ".ini"); |
1452 | - if (sc->overrideable()) |
1453 | - { |
1454 | - p->overridable_scopes.insert(path); |
1455 | - } |
1456 | - p->scopes[scope_id] = move(sc); |
1457 | - } |
1458 | - for (const auto &path : oem_files) |
1459 | - { |
1460 | - unique_ptr<ScopeConfig> sc(new ScopeConfig(path)); |
1461 | - string file_name = basename(const_cast<char*>(string(path).c_str())); |
1462 | - string scope_id = strip_suffix(file_name, ".ini"); |
1463 | - if (p->scopes.find(scope_id) != p->scopes.end()) |
1464 | - { |
1465 | - if (p->overridable_scopes.find(scope_id) != p->overridable_scopes.end()) |
1466 | - { |
1467 | - p->scopes[scope_id] = move(sc); |
1468 | - } |
1469 | - else |
1470 | - { |
1471 | - // print error about trying to override a non-overridable scope. |
1472 | - } |
1473 | - } |
1474 | - else |
1475 | - { |
1476 | - p->scopes[scope_id] = move(sc); |
1477 | - } |
1478 | - } |
1479 | - // Add click scope parsing here. |
1480 | -} |
1481 | - |
1482 | -ScopeSet::~ScopeSet() |
1483 | -{ |
1484 | - delete p; |
1485 | -} |
1486 | - |
1487 | -std::vector<std::string> ScopeSet::list() const |
1488 | -{ |
1489 | - vector<string> list; |
1490 | - for (auto &i : p->scopes) |
1491 | - { |
1492 | - list.push_back(i.first); |
1493 | - } |
1494 | - return list; |
1495 | -} |
1496 | - |
1497 | -const unity::scopes::internal::ScopeConfig& |
1498 | -ScopeSet::get(const std::string& name) |
1499 | -{ |
1500 | - if (p->scopes.find(name) == p->scopes.end()) |
1501 | - { |
1502 | - throw NotFoundException("Scope does not exist", name); |
1503 | - } |
1504 | - return *p->scopes[name].get(); |
1505 | -} |
1506 | - |
1507 | -} |
1508 | |
1509 | === removed file 'scoperegistry/ScopeSet.h' |
1510 | --- scoperegistry/ScopeSet.h 2014-01-14 13:36:43 +0000 |
1511 | +++ scoperegistry/ScopeSet.h 1970-01-01 00:00:00 +0000 |
1512 | @@ -1,56 +0,0 @@ |
1513 | -/* |
1514 | - * Copyright (C) 2013 Canonical Ltd |
1515 | - * |
1516 | - * This program is free software: you can redistribute it and/or modify |
1517 | - * it under the terms of the Lesser GNU General Public License version 3 as |
1518 | - * published by the Free Software Foundation. |
1519 | - * |
1520 | - * This program is distributed in the hope that it will be useful, |
1521 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1522 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1523 | - * GNU Lesser General Public License for more details. |
1524 | - * |
1525 | - * You should have received a copy of the GNU Lesser General Public License |
1526 | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1527 | - * |
1528 | - * Authored by: Jussi Pakkanen <jussi.pakkanen@canonical.com> |
1529 | - */ |
1530 | - |
1531 | -#ifndef SCOPEREGISTRY_SCOPESET_H_ |
1532 | -#define SCOPEREGISTRY_SCOPESET_H_ |
1533 | - |
1534 | -#include<vector> |
1535 | -#include<string> |
1536 | -#include<unity/scopes/internal/RegistryConfig.h> |
1537 | -#include<unity/scopes/internal/ScopeConfig.h> |
1538 | - |
1539 | - |
1540 | -namespace scoperegistry |
1541 | -{ |
1542 | - |
1543 | -struct ScopeSetPrivate; |
1544 | - |
1545 | - |
1546 | -class ScopeSet final |
1547 | -{ |
1548 | - |
1549 | -public: |
1550 | - |
1551 | - ScopeSet(const ::unity::scopes::internal::RegistryConfig& c); |
1552 | - ~ScopeSet(); |
1553 | - |
1554 | - ScopeSet(const ScopeSet&) = delete; |
1555 | - ScopeSet& operator=(const ScopeSet&) = delete; |
1556 | - |
1557 | - std::vector<std::string> list() const; |
1558 | - const unity::scopes::internal::ScopeConfig& get(const std::string& name); |
1559 | - |
1560 | -private: |
1561 | - ScopeSetPrivate* p; |
1562 | - |
1563 | -}; |
1564 | - |
1565 | - |
1566 | -} |
1567 | - |
1568 | -#endif |
1569 | |
1570 | === modified file 'scoperegistry/scoperegistry.cpp' |
1571 | --- scoperegistry/scoperegistry.cpp 2014-05-14 17:26:34 +0000 |
1572 | +++ scoperegistry/scoperegistry.cpp 2014-05-21 14:02:43 +0000 |
1573 | @@ -136,7 +136,7 @@ |
1574 | map<string, string> fixed_scopes; // Scopes that the OEM cannot override |
1575 | map<string, string> overrideable_scopes; // Scopes that the OEM can override |
1576 | |
1577 | - auto config_files = find_scope_config_files(scope_installdir, ".ini"); |
1578 | + auto config_files = find_scope_config_files(scope_installdir, ".ini", error); |
1579 | for (auto&& path : config_files) |
1580 | { |
1581 | filesystem::path p(path); |
1582 | @@ -163,7 +163,7 @@ |
1583 | { |
1584 | try |
1585 | { |
1586 | - auto oem_paths = find_scope_config_files(oem_installdir, ".ini"); |
1587 | + auto oem_paths = find_scope_config_files(oem_installdir, ".ini", error); |
1588 | for (auto&& path : oem_paths) |
1589 | { |
1590 | filesystem::path p(path); |
1591 | @@ -199,7 +199,7 @@ |
1592 | { |
1593 | try |
1594 | { |
1595 | - auto click_paths = find_scope_config_files(click_installdir, ".ini"); |
1596 | + auto click_paths = find_scope_config_files(click_installdir, ".ini", error); |
1597 | for (auto&& path : click_paths) |
1598 | { |
1599 | filesystem::path p(path); |
1600 | @@ -424,7 +424,6 @@ |
1601 | |
1602 | add_local_scopes(registry, local_scopes, middleware, scoperunner_path, config_file, false, process_timeout); |
1603 | add_local_scopes(registry, click_scopes, middleware, scoperunner_path, config_file, true, process_timeout); |
1604 | - local_scopes.insert(click_scopes.begin(), click_scopes.end()); |
1605 | if (ss_reg_id.empty()) |
1606 | { |
1607 | error("no remote registry configured, only local scopes will be available"); |
1608 | |
1609 | === modified file 'scoperunner/scoperunner.cpp' |
1610 | --- scoperunner/scoperunner.cpp 2014-05-09 04:04:06 +0000 |
1611 | +++ scoperunner/scoperunner.cpp 2014-05-21 14:02:43 +0000 |
1612 | @@ -93,7 +93,37 @@ |
1613 | auto rt = RuntimeImpl::create(scope_id, runtime_config); |
1614 | auto mw = rt->factory()->create(scope_id, reg_conf.mw_kind(), reg_conf.mw_configfile()); |
1615 | |
1616 | - ScopeLoader::SPtr loader = ScopeLoader::load(scope_id, lib_dir + "lib" + scope_id + ".so", rt->registry()); |
1617 | + // For a scope_id "Fred", we look for the library as "libFred.so", "Fred.so", and "scope.so". |
1618 | + vector<string> libs; |
1619 | + libs.push_back(lib_dir + "lib" + scope_id + ".so"); |
1620 | + libs.push_back(lib_dir + scope_id + ".so"); |
1621 | + libs.push_back(lib_dir + "scope.so"); |
1622 | + string failed_libs; |
1623 | + ScopeLoader::SPtr loader; |
1624 | + exception_ptr ep; |
1625 | + for (auto const& lib : libs) |
1626 | + { |
1627 | + try |
1628 | + { |
1629 | + loader = ScopeLoader::load(scope_id, lib, rt->registry()); |
1630 | + } |
1631 | + catch (unity::ResourceException& e) |
1632 | + { |
1633 | + failed_libs += "\n " + lib; |
1634 | + ep = e.remember(ep); |
1635 | + } |
1636 | + if (loader) |
1637 | + { |
1638 | + break; |
1639 | + } |
1640 | + } |
1641 | + if (!loader) |
1642 | + { |
1643 | + unity::ResourceException e("Cannot load scope " + scope_id + "; tried in the following locations:" |
1644 | + + failed_libs); |
1645 | + e.remember(ep); |
1646 | + throw e; |
1647 | + } |
1648 | loader->start(); |
1649 | |
1650 | // Give a thread to the scope to do with as it likes. If the scope doesn't want to use it and |
1651 | |
1652 | === modified file 'src/scopes/CMakeLists.txt' |
1653 | --- src/scopes/CMakeLists.txt 2014-05-08 14:49:31 +0000 |
1654 | +++ src/scopes/CMakeLists.txt 2014-05-21 14:02:43 +0000 |
1655 | @@ -29,6 +29,8 @@ |
1656 | ${CMAKE_CURRENT_SOURCE_DIR}/PreviewWidget.cpp |
1657 | ${CMAKE_CURRENT_SOURCE_DIR}/QueryBase.cpp |
1658 | ${CMAKE_CURRENT_SOURCE_DIR}/QueryCtrl.cpp |
1659 | + ${CMAKE_CURRENT_SOURCE_DIR}/RadioButtonsFilter.cpp |
1660 | + ${CMAKE_CURRENT_SOURCE_DIR}/RatingFilter.cpp |
1661 | ${CMAKE_CURRENT_SOURCE_DIR}/Registry.cpp |
1662 | ${CMAKE_CURRENT_SOURCE_DIR}/Reply.cpp |
1663 | ${CMAKE_CURRENT_SOURCE_DIR}/Result.cpp |
1664 | |
1665 | === modified file 'src/scopes/OptionSelectorFilter.cpp' |
1666 | --- src/scopes/OptionSelectorFilter.cpp 2014-05-08 16:10:18 +0000 |
1667 | +++ src/scopes/OptionSelectorFilter.cpp 2014-05-21 14:02:43 +0000 |
1668 | @@ -30,9 +30,9 @@ |
1669 | { |
1670 | } |
1671 | |
1672 | -OptionSelectorFilter::SPtr OptionSelectorFilter::create(std::string const& id, std::string const& label, bool multi_select) |
1673 | +OptionSelectorFilter::UPtr OptionSelectorFilter::create(std::string const& id, std::string const& label, bool multi_select) |
1674 | { |
1675 | - return std::shared_ptr<OptionSelectorFilter>(new OptionSelectorFilter(new internal::OptionSelectorFilterImpl(id, label, multi_select))); |
1676 | + return std::unique_ptr<OptionSelectorFilter>(new OptionSelectorFilter(new internal::OptionSelectorFilterImpl(id, label, multi_select))); |
1677 | } |
1678 | |
1679 | std::string OptionSelectorFilter::label() const |
1680 | @@ -55,6 +55,11 @@ |
1681 | return fwd()->options(); |
1682 | } |
1683 | |
1684 | +bool OptionSelectorFilter::has_active_option(FilterState const& filter_state) const |
1685 | +{ |
1686 | + return fwd()->has_active_option(filter_state); |
1687 | +} |
1688 | + |
1689 | std::set<FilterOption::SCPtr> OptionSelectorFilter::active_options(FilterState const& filter_state) const |
1690 | { |
1691 | return fwd()->active_options(filter_state); |
1692 | |
1693 | === added file 'src/scopes/RadioButtonsFilter.cpp' |
1694 | --- src/scopes/RadioButtonsFilter.cpp 1970-01-01 00:00:00 +0000 |
1695 | +++ src/scopes/RadioButtonsFilter.cpp 2014-05-21 14:02:43 +0000 |
1696 | @@ -0,0 +1,80 @@ |
1697 | +/* |
1698 | + * Copyright (C) 2014 Canonical Ltd |
1699 | + * |
1700 | + * This program is free software: you can redistribute it and/or modify |
1701 | + * it under the terms of the GNU Lesser General Public License version 3 as |
1702 | + * published by the Free Software Foundation. |
1703 | + * |
1704 | + * This program is distributed in the hope that it will be useful, |
1705 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1706 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1707 | + * GNU Lesser General Public License for more details. |
1708 | + * |
1709 | + * You should have received a copy of the GNU Lesser General Public License |
1710 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1711 | + * |
1712 | + * Authored by: Pawel Stolowski <pawel.stolowski@canonical.com> |
1713 | +*/ |
1714 | + |
1715 | +#include <unity/scopes/RadioButtonsFilter.h> |
1716 | +#include <unity/scopes/internal/RadioButtonsFilterImpl.h> |
1717 | + |
1718 | +namespace unity |
1719 | +{ |
1720 | + |
1721 | +namespace scopes |
1722 | +{ |
1723 | + |
1724 | +RadioButtonsFilter::RadioButtonsFilter(internal::RadioButtonsFilterImpl *impl) |
1725 | + : FilterBase(impl) |
1726 | +{ |
1727 | +} |
1728 | + |
1729 | +FilterOption::SCPtr RadioButtonsFilter::add_option(std::string const& id, std::string const& label) |
1730 | +{ |
1731 | + return fwd()->add_option(id, label); |
1732 | +} |
1733 | + |
1734 | +std::string RadioButtonsFilter::label() const |
1735 | +{ |
1736 | + return fwd()->label(); |
1737 | +} |
1738 | + |
1739 | +FilterOption::SCPtr RadioButtonsFilter::active_option(FilterState const& filter_state) const |
1740 | +{ |
1741 | + return fwd()->active_option(filter_state); |
1742 | +} |
1743 | + |
1744 | +bool RadioButtonsFilter::has_active_option(FilterState const& filter_state) const |
1745 | +{ |
1746 | + return fwd()->has_active_option(filter_state); |
1747 | +} |
1748 | + |
1749 | +std::list<FilterOption::SCPtr> RadioButtonsFilter::options() const |
1750 | +{ |
1751 | + return fwd()->options(); |
1752 | +} |
1753 | + |
1754 | +void RadioButtonsFilter::update_state(FilterState& filter_state, FilterOption::SCPtr option, bool active) const |
1755 | +{ |
1756 | + fwd()->update_state(filter_state, option, active); |
1757 | +} |
1758 | + |
1759 | +void RadioButtonsFilter::update_state(FilterState& filter_state, std::string const& filter_id, std::string const& option_id, bool value) |
1760 | +{ |
1761 | + internal::RadioButtonsFilterImpl::update_state(filter_state, filter_id, option_id, value); |
1762 | +} |
1763 | + |
1764 | +RadioButtonsFilter::UPtr RadioButtonsFilter::create(std::string const& id, std::string const& label) |
1765 | +{ |
1766 | + return std::unique_ptr<RadioButtonsFilter>(new RadioButtonsFilter(new internal::RadioButtonsFilterImpl(id, label))); |
1767 | +} |
1768 | + |
1769 | +internal::RadioButtonsFilterImpl* RadioButtonsFilter::fwd() const |
1770 | +{ |
1771 | + return dynamic_cast<internal::RadioButtonsFilterImpl*>(p.get()); |
1772 | +} |
1773 | + |
1774 | +} // namespace scopes |
1775 | + |
1776 | +} // namespace unity |
1777 | |
1778 | === added file 'src/scopes/RatingFilter.cpp' |
1779 | --- src/scopes/RatingFilter.cpp 1970-01-01 00:00:00 +0000 |
1780 | +++ src/scopes/RatingFilter.cpp 2014-05-21 14:02:43 +0000 |
1781 | @@ -0,0 +1,105 @@ |
1782 | +/* |
1783 | + * Copyright (C) 2014 Canonical Ltd |
1784 | + * |
1785 | + * This program is free software: you can redistribute it and/or modify |
1786 | + * it under the terms of the GNU Lesser General Public License version 3 as |
1787 | + * published by the Free Software Foundation. |
1788 | + * |
1789 | + * This program is distributed in the hope that it will be useful, |
1790 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1791 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1792 | + * GNU Lesser General Public License for more details. |
1793 | + * |
1794 | + * You should have received a copy of the GNU Lesser General Public License |
1795 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1796 | + * |
1797 | + * Authored by: Pawel Stolowski <pawel.stolowski@canonical.com> |
1798 | +*/ |
1799 | + |
1800 | +#include <unity/scopes/RatingFilter.h> |
1801 | +#include <unity/scopes/internal/RatingFilterImpl.h> |
1802 | + |
1803 | +namespace unity |
1804 | +{ |
1805 | + |
1806 | +namespace scopes |
1807 | +{ |
1808 | + |
1809 | +RatingFilter::RatingFilter(internal::RatingFilterImpl *impl) |
1810 | + : FilterBase(impl) |
1811 | +{ |
1812 | +} |
1813 | + |
1814 | +RatingFilter::UPtr RatingFilter::create(std::string const& id, std::string const& label, int top_rating) |
1815 | +{ |
1816 | + return std::unique_ptr<RatingFilter>(new RatingFilter(new internal::RatingFilterImpl(id, label, top_rating))); |
1817 | +} |
1818 | + |
1819 | +RatingFilter::UPtr RatingFilter::create(std::string const& id, std::string const& label) |
1820 | +{ |
1821 | + return std::unique_ptr<RatingFilter>(new RatingFilter(new internal::RatingFilterImpl(id, label))); |
1822 | +} |
1823 | + |
1824 | +FilterOption::SCPtr RatingFilter::add_option(std::string const& id, std::string const& label) |
1825 | +{ |
1826 | + return fwd()->add_option(id, label); |
1827 | +} |
1828 | + |
1829 | +void RatingFilter::set_on_icon(std::string const& on_icon) |
1830 | +{ |
1831 | + fwd()->set_on_icon(on_icon); |
1832 | +} |
1833 | + |
1834 | +void RatingFilter::set_off_icon(std::string const& off_icon) |
1835 | +{ |
1836 | + fwd()->set_off_icon(off_icon); |
1837 | +} |
1838 | + |
1839 | +std::string RatingFilter::label() const |
1840 | +{ |
1841 | + return fwd()->label(); |
1842 | +} |
1843 | + |
1844 | +std::list<FilterOption::SCPtr> RatingFilter::options() const |
1845 | +{ |
1846 | + return fwd()->options(); |
1847 | +} |
1848 | + |
1849 | +std::string RatingFilter::on_icon() const |
1850 | +{ |
1851 | + return fwd()->on_icon(); |
1852 | +} |
1853 | + |
1854 | +std::string RatingFilter::off_icon() const |
1855 | +{ |
1856 | + return fwd()->off_icon(); |
1857 | +} |
1858 | + |
1859 | +FilterOption::SCPtr RatingFilter::active_rating(FilterState const& filter_state) const |
1860 | +{ |
1861 | + return fwd()->active_option(filter_state); |
1862 | +} |
1863 | + |
1864 | +bool RatingFilter::has_active_rating(FilterState const& filter_state) const |
1865 | +{ |
1866 | + return fwd()->has_active_option(filter_state); |
1867 | +} |
1868 | + |
1869 | +void RatingFilter::update_state(FilterState& filter_state, FilterOption::SCPtr option, bool active) const |
1870 | +{ |
1871 | + fwd()->update_state(filter_state, option, active); |
1872 | +} |
1873 | + |
1874 | +void RatingFilter::update_state(FilterState& filter_state, std::string const& filter_id, std::string const& option_id, bool value) |
1875 | +{ |
1876 | + internal::RatingFilterImpl::update_state(filter_state, filter_id, option_id, value); |
1877 | +} |
1878 | + |
1879 | +internal::RatingFilterImpl* RatingFilter::fwd() const |
1880 | +{ |
1881 | + return dynamic_cast<internal::RatingFilterImpl*>(p.get()); |
1882 | +} |
1883 | + |
1884 | +} // namespace scopes |
1885 | + |
1886 | +} // namespace unity |
1887 | |
1888 | === modified file 'src/scopes/internal/CMakeLists.txt' |
1889 | --- src/scopes/internal/CMakeLists.txt 2014-05-08 14:49:31 +0000 |
1890 | +++ src/scopes/internal/CMakeLists.txt 2014-05-21 14:02:43 +0000 |
1891 | @@ -29,12 +29,14 @@ |
1892 | ${CMAKE_CURRENT_SOURCE_DIR}/MiddlewareBase.cpp |
1893 | ${CMAKE_CURRENT_SOURCE_DIR}/MiddlewareFactory.cpp |
1894 | ${CMAKE_CURRENT_SOURCE_DIR}/MWObject.cpp |
1895 | + ${CMAKE_CURRENT_SOURCE_DIR}/MWPublisher.cpp |
1896 | ${CMAKE_CURRENT_SOURCE_DIR}/MWQuery.cpp |
1897 | ${CMAKE_CURRENT_SOURCE_DIR}/MWQueryCtrl.cpp |
1898 | ${CMAKE_CURRENT_SOURCE_DIR}/MWRegistry.cpp |
1899 | ${CMAKE_CURRENT_SOURCE_DIR}/MWReply.cpp |
1900 | ${CMAKE_CURRENT_SOURCE_DIR}/MWScope.cpp |
1901 | ${CMAKE_CURRENT_SOURCE_DIR}/MWStateReceiver.cpp |
1902 | + ${CMAKE_CURRENT_SOURCE_DIR}/MWSubscriber.cpp |
1903 | ${CMAKE_CURRENT_SOURCE_DIR}/ObjectImpl.cpp |
1904 | ${CMAKE_CURRENT_SOURCE_DIR}/OptionSelectorFilterImpl.cpp |
1905 | ${CMAKE_CURRENT_SOURCE_DIR}/PreviewQueryObject.cpp |
1906 | @@ -46,6 +48,8 @@ |
1907 | ${CMAKE_CURRENT_SOURCE_DIR}/QueryCtrlObject.cpp |
1908 | ${CMAKE_CURRENT_SOURCE_DIR}/QueryMetadataImpl.cpp |
1909 | ${CMAKE_CURRENT_SOURCE_DIR}/QueryObject.cpp |
1910 | + ${CMAKE_CURRENT_SOURCE_DIR}/RadioButtonsFilterImpl.cpp |
1911 | + ${CMAKE_CURRENT_SOURCE_DIR}/RatingFilterImpl.cpp |
1912 | ${CMAKE_CURRENT_SOURCE_DIR}/RangeInputFilterImpl.cpp |
1913 | ${CMAKE_CURRENT_SOURCE_DIR}/Reaper.cpp |
1914 | ${CMAKE_CURRENT_SOURCE_DIR}/RegistryConfig.cpp |
1915 | |
1916 | === modified file 'src/scopes/internal/FilterBaseImpl.cpp' |
1917 | --- src/scopes/internal/FilterBaseImpl.cpp 2014-05-15 22:32:00 +0000 |
1918 | +++ src/scopes/internal/FilterBaseImpl.cpp 2014-05-21 14:02:43 +0000 |
1919 | @@ -22,6 +22,8 @@ |
1920 | #include <unity/scopes/internal/Utils.h> |
1921 | #include <unity/scopes/internal/OptionSelectorFilterImpl.h> |
1922 | #include <unity/scopes/internal/RangeInputFilterImpl.h> |
1923 | +#include <unity/scopes/internal/RadioButtonsFilterImpl.h> |
1924 | +#include <unity/scopes/internal/RatingFilterImpl.h> |
1925 | #include <unity/UnityExceptions.h> |
1926 | #include <sstream> |
1927 | |
1928 | @@ -117,6 +119,14 @@ |
1929 | { |
1930 | return RangeInputFilterImpl::create(var); |
1931 | } |
1932 | + if (ftype == "radio_buttons") |
1933 | + { |
1934 | + return RadioButtonsFilterImpl::create(var); |
1935 | + } |
1936 | + if (ftype == "rating") |
1937 | + { |
1938 | + return RatingFilterImpl::create(var); |
1939 | + } |
1940 | throw unity::LogicException("Unknown filter type: " + ftype); |
1941 | } |
1942 | throw unity::LogicException("FilterBase: Missing 'filter_type'"); |
1943 | @@ -142,6 +152,56 @@ |
1944 | return filters; |
1945 | } |
1946 | |
1947 | +void FilterBaseImpl::validate_filters(Filters const& filters) |
1948 | +{ |
1949 | + for (auto const& f: filters) |
1950 | + { |
1951 | + if (f == nullptr) |
1952 | + { |
1953 | + throw unity::LogicException("FilterBaseImpl::validate_filters(): invalid null filter pointer"); |
1954 | + } |
1955 | + { |
1956 | + OptionSelectorFilter::SCPtr optsel = std::dynamic_pointer_cast<OptionSelectorFilter const>(f); |
1957 | + if (optsel) |
1958 | + { |
1959 | + if (optsel->options().size() == 0) |
1960 | + { |
1961 | + std::stringstream err; |
1962 | + err << "FilterBaseImpl::validate_filters(): invalid empty OptionSelectorFilter '" << f->id() << "'"; |
1963 | + throw unity::LogicException(err.str()); |
1964 | + } |
1965 | + continue; |
1966 | + } |
1967 | + } |
1968 | + { |
1969 | + RatingFilter::SCPtr rating = std::dynamic_pointer_cast<RatingFilter const>(f); |
1970 | + if (rating) |
1971 | + { |
1972 | + if (rating->options().size() == 0) |
1973 | + { |
1974 | + std::stringstream err; |
1975 | + err << "FilterBaseImpl::validate_filters(): invalid empty RatingFilter '" << f->id() << "'"; |
1976 | + throw unity::LogicException(err.str()); |
1977 | + } |
1978 | + continue; |
1979 | + } |
1980 | + } |
1981 | + { |
1982 | + RadioButtonsFilter::SCPtr radiobtn = std::dynamic_pointer_cast<RadioButtonsFilter const>(f); |
1983 | + if (radiobtn) |
1984 | + { |
1985 | + if (radiobtn->options().size() == 0) |
1986 | + { |
1987 | + std::stringstream err; |
1988 | + err << "FilterBaseImpl::validate_filters(): invalid empty RadioButtonsFilter '" << f->id() << "'"; |
1989 | + throw unity::LogicException(err.str()); |
1990 | + } |
1991 | + continue; |
1992 | + } |
1993 | + } |
1994 | + } |
1995 | +} |
1996 | + |
1997 | } // namespace internal |
1998 | |
1999 | } // namespace scopes |
2000 | |
2001 | === added file 'src/scopes/internal/MWPublisher.cpp' |
2002 | --- src/scopes/internal/MWPublisher.cpp 1970-01-01 00:00:00 +0000 |
2003 | +++ src/scopes/internal/MWPublisher.cpp 2014-05-21 14:02:43 +0000 |
2004 | @@ -0,0 +1,42 @@ |
2005 | +/* |
2006 | + * Copyright (C) 2014 Canonical Ltd |
2007 | + * |
2008 | + * This program is free software: you can redistribute it and/or modify |
2009 | + * it under the terms of the GNU Lesser General Public License version 3 as |
2010 | + * published by the Free Software Foundation. |
2011 | + * |
2012 | + * This program is distributed in the hope that it will be useful, |
2013 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2014 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2015 | + * GNU Lesser General Public License for more details. |
2016 | + * |
2017 | + * You should have received a copy of the GNU Lesser General Public License |
2018 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
2019 | + * |
2020 | + * Authored by: Marcus Tomlinson <marcus.tomlinson@canonical.com> |
2021 | + */ |
2022 | + |
2023 | +#include <unity/scopes/internal/MWPublisher.h> |
2024 | + |
2025 | +namespace unity |
2026 | +{ |
2027 | + |
2028 | +namespace scopes |
2029 | +{ |
2030 | + |
2031 | +namespace internal |
2032 | +{ |
2033 | + |
2034 | +MWPublisher::MWPublisher() |
2035 | +{ |
2036 | +} |
2037 | + |
2038 | +MWPublisher::~MWPublisher() |
2039 | +{ |
2040 | +} |
2041 | + |
2042 | +} // namespace internal |
2043 | + |
2044 | +} // namespace scopes |
2045 | + |
2046 | +} // namespace unity |
2047 | |
2048 | === added file 'src/scopes/internal/MWSubscriber.cpp' |
2049 | --- src/scopes/internal/MWSubscriber.cpp 1970-01-01 00:00:00 +0000 |
2050 | +++ src/scopes/internal/MWSubscriber.cpp 2014-05-21 14:02:43 +0000 |
2051 | @@ -0,0 +1,42 @@ |
2052 | +/* |
2053 | + * Copyright (C) 2014 Canonical Ltd |
2054 | + * |
2055 | + * This program is free software: you can redistribute it and/or modify |
2056 | + * it under the terms of the GNU Lesser General Public License version 3 as |
2057 | + * published by the Free Software Foundation. |
2058 | + * |
2059 | + * This program is distributed in the hope that it will be useful, |
2060 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2061 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2062 | + * GNU Lesser General Public License for more details. |
2063 | + * |
2064 | + * You should have received a copy of the GNU Lesser General Public License |
2065 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
2066 | + * |
2067 | + * Authored by: Marcus Tomlinson <marcus.tomlinson@canonical.com> |
2068 | + */ |
2069 | + |
2070 | +#include <unity/scopes/internal/MWSubscriber.h> |
2071 | + |
2072 | +namespace unity |
2073 | +{ |
2074 | + |
2075 | +namespace scopes |
2076 | +{ |
2077 | + |
2078 | +namespace internal |
2079 | +{ |
2080 | + |
2081 | +MWSubscriber::MWSubscriber() |
2082 | +{ |
2083 | +} |
2084 | + |
2085 | +MWSubscriber::~MWSubscriber() |
2086 | +{ |
2087 | +} |
2088 | + |
2089 | +} // namespace internal |
2090 | + |
2091 | +} // namespace scopes |
2092 | + |
2093 | +} // namespace unity |
2094 | |
2095 | === modified file 'src/scopes/internal/OptionSelectorFilterImpl.cpp' |
2096 | --- src/scopes/internal/OptionSelectorFilterImpl.cpp 2014-05-15 03:23:43 +0000 |
2097 | +++ src/scopes/internal/OptionSelectorFilterImpl.cpp 2014-05-21 14:02:43 +0000 |
2098 | @@ -131,6 +131,11 @@ |
2099 | } |
2100 | } |
2101 | |
2102 | +int OptionSelectorFilterImpl::num_of_options() const |
2103 | +{ |
2104 | + return options_.size(); |
2105 | +} |
2106 | + |
2107 | std::list<FilterOption::SCPtr> OptionSelectorFilterImpl::options() const |
2108 | { |
2109 | return options_; |
2110 | @@ -170,6 +175,33 @@ |
2111 | return opts; |
2112 | } |
2113 | |
2114 | +bool OptionSelectorFilterImpl::has_active_option(FilterState const& filter_state) const |
2115 | +{ |
2116 | + if (filter_state.has_filter(id())) |
2117 | + { |
2118 | + try |
2119 | + { |
2120 | + auto const var = FilterBaseImpl::get(filter_state, id()).get_array(); // this can throw if of different type |
2121 | + |
2122 | + for (auto const& idvar: var) |
2123 | + { |
2124 | + auto const opt_id = idvar.get_string(); |
2125 | + for (auto const& opt: options_) |
2126 | + { |
2127 | + if (opt_id == opt->id()) |
2128 | + { |
2129 | + return true; |
2130 | + } |
2131 | + } |
2132 | + } |
2133 | + } |
2134 | + catch (...) |
2135 | + { |
2136 | + } |
2137 | + } |
2138 | + return false; |
2139 | +} |
2140 | + |
2141 | void OptionSelectorFilterImpl::update_state(FilterState& filter_state, FilterOption::SCPtr option, bool active) const |
2142 | { |
2143 | auto const oid(option->id()); |
2144 | |
2145 | === added file 'src/scopes/internal/RadioButtonsFilterImpl.cpp' |
2146 | --- src/scopes/internal/RadioButtonsFilterImpl.cpp 1970-01-01 00:00:00 +0000 |
2147 | +++ src/scopes/internal/RadioButtonsFilterImpl.cpp 2014-05-21 14:02:43 +0000 |
2148 | @@ -0,0 +1,81 @@ |
2149 | +/* |
2150 | + * Copyright (C) 2014 Canonical Ltd |
2151 | + * |
2152 | + * This program is free software: you can redistribute it and/or modify |
2153 | + * it under the terms of the GNU Lesser General Public License version 3 as |
2154 | + * published by the Free Software Foundation. |
2155 | + * |
2156 | + * This program is distributed in the hope that it will be useful, |
2157 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2158 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2159 | + * GNU Lesser General Public License for more details. |
2160 | + * |
2161 | + * You should have received a copy of the GNU Lesser General Public License |
2162 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
2163 | + * |
2164 | + * Authored by: Pawel Stolowski <pawel.stolowski@canonical.com> |
2165 | +*/ |
2166 | + |
2167 | +#include <unity/scopes/internal/RadioButtonsFilterImpl.h> |
2168 | +#include <unity/scopes/FilterState.h> |
2169 | +#include <sstream> |
2170 | +#include <unity/UnityExceptions.h> |
2171 | + |
2172 | +namespace unity |
2173 | +{ |
2174 | + |
2175 | +namespace scopes |
2176 | +{ |
2177 | + |
2178 | +namespace internal |
2179 | +{ |
2180 | + |
2181 | +RadioButtonsFilterImpl::RadioButtonsFilterImpl(std::string const& id, std::string const& label) |
2182 | + : OptionSelectorFilterImpl(id, label, false) |
2183 | +{ |
2184 | +} |
2185 | + |
2186 | +RadioButtonsFilterImpl::RadioButtonsFilterImpl(VariantMap const& var) |
2187 | + : OptionSelectorFilterImpl(var) |
2188 | +{ |
2189 | + if (multi_select()) // this should never happen unless a client bypasses the api |
2190 | + { |
2191 | + std::stringstream err; |
2192 | + err << "RadioButtonsFilterImpl(): invalid filter data, multi selection is not available with RadioButtonsFilter, filter id '" << id() << "'"; |
2193 | + throw unity::LogicException(err.str()); |
2194 | + } |
2195 | +} |
2196 | + |
2197 | +FilterOption::SCPtr RadioButtonsFilterImpl::active_option(FilterState const& filter_state) const |
2198 | +{ |
2199 | + auto const active = active_options(filter_state); |
2200 | + if (active.size() > 1) // this should never happen unless a client bypasses the api |
2201 | + { |
2202 | + std::stringstream err; |
2203 | + err << "RadioButtonsFilterImpl::active_option(): internal error, more than one button active, filter id '" << id() << "'"; |
2204 | + throw unity::LogicException(err.str()); |
2205 | + } |
2206 | + |
2207 | + if (active.size() == 1) |
2208 | + { |
2209 | + return *active.begin(); |
2210 | + } |
2211 | + |
2212 | + return nullptr; |
2213 | +} |
2214 | + |
2215 | +std::string RadioButtonsFilterImpl::filter_type() const |
2216 | +{ |
2217 | + return "radio_buttons"; |
2218 | +} |
2219 | + |
2220 | +RadioButtonsFilter::SPtr RadioButtonsFilterImpl::create(VariantMap const& var) |
2221 | +{ |
2222 | + return std::shared_ptr<RadioButtonsFilter>(new RadioButtonsFilter(new RadioButtonsFilterImpl(var))); |
2223 | +} |
2224 | + |
2225 | +} // namespace internal |
2226 | + |
2227 | +} // namespace scopes |
2228 | + |
2229 | +} // namespace unity |
2230 | |
2231 | === added file 'src/scopes/internal/RatingFilterImpl.cpp' |
2232 | --- src/scopes/internal/RatingFilterImpl.cpp 1970-01-01 00:00:00 +0000 |
2233 | +++ src/scopes/internal/RatingFilterImpl.cpp 2014-05-21 14:02:43 +0000 |
2234 | @@ -0,0 +1,109 @@ |
2235 | +/* |
2236 | + * Copyright (C) 2014 Canonical Ltd |
2237 | + * |
2238 | + * This program is free software: you can redistribute it and/or modify |
2239 | + * it under the terms of the GNU Lesser General Public License version 3 as |
2240 | + * published by the Free Software Foundation. |
2241 | + * |
2242 | + * This program is distributed in the hope that it will be useful, |
2243 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2244 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2245 | + * GNU Lesser General Public License for more details. |
2246 | + * |
2247 | + * You should have received a copy of the GNU Lesser General Public License |
2248 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
2249 | + * |
2250 | + * Authored by: Pawel Stolowski <pawel.stolowski@canonical.com> |
2251 | +*/ |
2252 | + |
2253 | +#include <unity/scopes/RatingFilter.h> |
2254 | +#include <unity/scopes/internal/RatingFilterImpl.h> |
2255 | +#include <unity/UnityExceptions.h> |
2256 | +#include <sstream> |
2257 | + |
2258 | +namespace unity |
2259 | +{ |
2260 | + |
2261 | +namespace scopes |
2262 | +{ |
2263 | + |
2264 | +namespace internal |
2265 | +{ |
2266 | + |
2267 | +RatingFilterImpl::RatingFilterImpl(std::string const& id, std::string const& label) |
2268 | + : RadioButtonsFilterImpl(id, label) |
2269 | +{ |
2270 | +} |
2271 | + |
2272 | +RatingFilterImpl::RatingFilterImpl(std::string const& id, std::string const& label, int top_rating) |
2273 | + : RadioButtonsFilterImpl(id, label) |
2274 | +{ |
2275 | + if (top_rating < 2 || top_rating > max_rating) |
2276 | + { |
2277 | + std::stringstream err; |
2278 | + err << "RatingFilterImpl(): top_rating " << top_rating << " outside of allowed range for filter '" << id << "'"; |
2279 | + throw unity::LogicException(err.str()); |
2280 | + } |
2281 | + |
2282 | + // create rating options from 1..top_rating range, e.g. "1+", "2+", ..., "5". |
2283 | + for (int i = 1; i <= top_rating; i++) |
2284 | + { |
2285 | + auto const num = std::to_string(i); |
2286 | + RadioButtonsFilterImpl::add_option(num, i < top_rating ? num + "+" : num); |
2287 | + } |
2288 | +} |
2289 | + |
2290 | +RatingFilterImpl::RatingFilterImpl(VariantMap const& var) |
2291 | + : RadioButtonsFilterImpl(var) |
2292 | +{ |
2293 | +} |
2294 | + |
2295 | +FilterOption::SCPtr RatingFilterImpl::add_option(std::string const& id, std::string const& label) |
2296 | +{ |
2297 | + if (num_of_options() < max_rating) |
2298 | + { |
2299 | + return RadioButtonsFilterImpl::add_option(id, label); |
2300 | + } |
2301 | + else |
2302 | + { |
2303 | + std::stringstream err; |
2304 | + err << "RatingFilterImpl::add_option(): maximum number of rating options reached for filter '" << id << "'"; |
2305 | + throw unity::LogicException(err.str()); |
2306 | + } |
2307 | +} |
2308 | + |
2309 | +void RatingFilterImpl::set_on_icon(std::string const& on_icon) |
2310 | +{ |
2311 | + on_icon_ = on_icon; |
2312 | +} |
2313 | + |
2314 | +void RatingFilterImpl::set_off_icon(std::string const& off_icon) |
2315 | +{ |
2316 | + off_icon_ = off_icon; |
2317 | +} |
2318 | + |
2319 | +std::string RatingFilterImpl::on_icon() const |
2320 | +{ |
2321 | + return on_icon_; |
2322 | +} |
2323 | + |
2324 | +std::string RatingFilterImpl::off_icon() const |
2325 | +{ |
2326 | + return off_icon_; |
2327 | +} |
2328 | + |
2329 | +RatingFilter::SPtr RatingFilterImpl::create(VariantMap const& var) |
2330 | +{ |
2331 | + return std::shared_ptr<RatingFilter>(new RatingFilter(new RatingFilterImpl(var))); |
2332 | +} |
2333 | + |
2334 | +std::string RatingFilterImpl::filter_type() const |
2335 | +{ |
2336 | + return "rating"; |
2337 | +} |
2338 | + |
2339 | +} // namespace internal |
2340 | + |
2341 | +} // namespace scopes |
2342 | + |
2343 | +} // namespace unity |
2344 | |
2345 | === modified file 'src/scopes/internal/SearchReplyImpl.cpp' |
2346 | --- src/scopes/internal/SearchReplyImpl.cpp 2014-04-29 11:20:57 +0000 |
2347 | +++ src/scopes/internal/SearchReplyImpl.cpp 2014-05-21 14:02:43 +0000 |
2348 | @@ -62,7 +62,7 @@ |
2349 | } |
2350 | catch (unity::LogicException const &e) |
2351 | { |
2352 | - throw unity::LogicException("Reply::register_departments(): Failed to validate departments"); |
2353 | + throw unity::LogicException("SearchReplyImpl::register_departments(): Failed to validate departments"); |
2354 | } |
2355 | |
2356 | ReplyImpl::push(internal::DepartmentImpl::serialize_departments(departments, current_department_id)); // ignore return value? |
2357 | @@ -129,6 +129,16 @@ |
2358 | |
2359 | bool SearchReplyImpl::push(unity::scopes::Filters const& filters, unity::scopes::FilterState const& filter_state) |
2360 | { |
2361 | + // basic consistency check |
2362 | + try |
2363 | + { |
2364 | + internal::FilterBaseImpl::validate_filters(filters); |
2365 | + } |
2366 | + catch (unity::LogicException const &e) |
2367 | + { |
2368 | + throw unity::LogicException("SearchReplyImpl::push(): Failed to validate filters"); |
2369 | + } |
2370 | + |
2371 | VariantMap var; |
2372 | var["filters"] = internal::FilterBaseImpl::serialize_filters(filters); |
2373 | var["filter_state"] = filter_state.serialize(); |
2374 | |
2375 | === modified file 'src/scopes/internal/smartscopes/SSRegistryObject.cpp' |
2376 | --- src/scopes/internal/smartscopes/SSRegistryObject.cpp 2014-05-09 08:20:57 +0000 |
2377 | +++ src/scopes/internal/smartscopes/SSRegistryObject.cpp 2014-05-21 14:02:43 +0000 |
2378 | @@ -232,6 +232,11 @@ |
2379 | metadata->set_art(*scope.art); |
2380 | } |
2381 | |
2382 | + if (scope.appearance) |
2383 | + { |
2384 | + metadata->set_appearance_attributes(*scope.appearance); |
2385 | + } |
2386 | + |
2387 | metadata->set_invisible(scope.invisible); |
2388 | |
2389 | ScopeProxy proxy = ScopeImpl::create(middleware_->create_scope_proxy(scope.id, ss_scope_endpoint_), |
2390 | |
2391 | === modified file 'src/scopes/internal/smartscopes/SmartScopesClient.cpp' |
2392 | --- src/scopes/internal/smartscopes/SmartScopesClient.cpp 2014-05-09 09:56:09 +0000 |
2393 | +++ src/scopes/internal/smartscopes/SmartScopesClient.cpp 2014-05-21 14:02:43 +0000 |
2394 | @@ -259,6 +259,11 @@ |
2395 | scope.art.reset(new std::string(child_node->get_node("art")->as_string())); |
2396 | } |
2397 | |
2398 | + if (child_node->has_node("appearance")) |
2399 | + { |
2400 | + scope.appearance.reset(new VariantMap(child_node->get_node("appearance")->to_variant().get_dict())); |
2401 | + } |
2402 | + |
2403 | scope.invisible = child_node->has_node("invisible") ? child_node->get_node("invisible")->as_bool() : false; |
2404 | |
2405 | remote_scopes.push_back(scope); |
2406 | |
2407 | === modified file 'src/scopes/internal/zmq_middleware/CMakeLists.txt' |
2408 | --- src/scopes/internal/zmq_middleware/CMakeLists.txt 2014-04-15 00:30:07 +0000 |
2409 | +++ src/scopes/internal/zmq_middleware/CMakeLists.txt 2014-05-21 14:02:43 +0000 |
2410 | @@ -21,6 +21,7 @@ |
2411 | ${CMAKE_CURRENT_SOURCE_DIR}/ZmqMiddleware.cpp |
2412 | ${CMAKE_CURRENT_SOURCE_DIR}/ZmqException.cpp |
2413 | ${CMAKE_CURRENT_SOURCE_DIR}/ZmqObject.cpp |
2414 | + ${CMAKE_CURRENT_SOURCE_DIR}/ZmqPublisher.cpp |
2415 | ${CMAKE_CURRENT_SOURCE_DIR}/ZmqQuery.cpp |
2416 | ${CMAKE_CURRENT_SOURCE_DIR}/ZmqQueryCtrl.cpp |
2417 | ${CMAKE_CURRENT_SOURCE_DIR}/ZmqReceiver.cpp |
2418 | @@ -29,5 +30,6 @@ |
2419 | ${CMAKE_CURRENT_SOURCE_DIR}/ZmqScope.cpp |
2420 | ${CMAKE_CURRENT_SOURCE_DIR}/ZmqSender.cpp |
2421 | ${CMAKE_CURRENT_SOURCE_DIR}/ZmqStateReceiver.cpp |
2422 | + ${CMAKE_CURRENT_SOURCE_DIR}/ZmqSubscriber.cpp |
2423 | ) |
2424 | set(UNITY_SCOPES_LIB_SRC ${UNITY_SCOPES_LIB_SRC} ${SRC} PARENT_SCOPE) |
2425 | |
2426 | === modified file 'src/scopes/internal/zmq_middleware/ObjectAdapter.cpp' |
2427 | --- src/scopes/internal/zmq_middleware/ObjectAdapter.cpp 2014-05-14 04:50:14 +0000 |
2428 | +++ src/scopes/internal/zmq_middleware/ObjectAdapter.cpp 2014-05-21 14:02:43 +0000 |
2429 | @@ -494,47 +494,6 @@ |
2430 | } |
2431 | } |
2432 | |
2433 | -// For the ipc transport, zmq permits more than one server to bind to the same endpoint. |
2434 | -// If a server binds to an endpoint while another server is using that endpoint, the |
2435 | -// second server silently "steals" the endpoint from the previous server, so all |
2436 | -// connects after that point go to the new server, while connects that happened earlier |
2437 | -// go to the old server. This is meant as a fail-over feature, and cannot be disabled. |
2438 | -// |
2439 | -// We don't want this and need an error if two servers try to use the same endpoint. |
2440 | -// Hacky solution: we check whether it's possible to successfully connect to the |
2441 | -// endpoint. If so, a server is still running there, and we throw. This has a |
2442 | -// small race because a second server may connect after the check, but before |
2443 | -// the bind. But, in practice, that's good enough for our purposes. |
2444 | - |
2445 | -void ObjectAdapter::safe_bind(zmqpp::socket& s, string const& endpoint) |
2446 | -{ |
2447 | - const std::string transport_prefix = "ipc://"; |
2448 | - if (endpoint.substr(0, transport_prefix.size()) == transport_prefix) |
2449 | - { |
2450 | - string path = endpoint.substr(transport_prefix.size()); |
2451 | - struct sockaddr_un addr; |
2452 | - memset(&addr, 0, sizeof(addr)); |
2453 | - addr.sun_family = AF_UNIX; |
2454 | - strncpy(addr.sun_path, path.c_str(), sizeof(addr.sun_path) - 1); |
2455 | - int fd = ::socket(AF_UNIX, SOCK_STREAM, 0); |
2456 | - if (fd == -1) |
2457 | - { |
2458 | - // LCOV_EXCL_START |
2459 | - throw MiddlewareException("ObjectAdapter: broker thread failure (adapter: " + name_ + "): " + |
2460 | - "cannot create socket: " + strerror(errno)); |
2461 | - // LCOV_EXCL_STOP |
2462 | - } |
2463 | - util::ResourcePtr<int, decltype(&::close)> close_guard(fd, ::close); |
2464 | - if (::connect(fd, (struct sockaddr*)&addr, sizeof(addr)) == 0) |
2465 | - { |
2466 | - // Connect succeeded, so another server is using the socket already. |
2467 | - throw MiddlewareException("ObjectAdapter: broker thread failure (adapter: " + name_ + "): " + |
2468 | - "address in use: " + endpoint); |
2469 | - } |
2470 | - } |
2471 | - s.bind(endpoint); |
2472 | -} |
2473 | - |
2474 | shared_ptr<ServantBase> ObjectAdapter::find_servant(string const& id, string const& category) |
2475 | { |
2476 | shared_ptr<ServantBase> servant = find(id); |
2477 | |
2478 | === modified file 'src/scopes/internal/zmq_middleware/Util.cpp' |
2479 | --- src/scopes/internal/zmq_middleware/Util.cpp 2014-01-28 06:34:03 +0000 |
2480 | +++ src/scopes/internal/zmq_middleware/Util.cpp 2014-05-21 14:02:43 +0000 |
2481 | @@ -19,7 +19,10 @@ |
2482 | #include <unity/scopes/internal/zmq_middleware/Util.h> |
2483 | |
2484 | #include <unity/scopes/ScopeExceptions.h> |
2485 | +#include <unity/util/ResourcePtr.h> |
2486 | |
2487 | +#include <unistd.h> |
2488 | +#include <sys/socket.h> |
2489 | #include <sys/un.h> |
2490 | |
2491 | using namespace std; |
2492 | @@ -55,6 +58,45 @@ |
2493 | } |
2494 | } |
2495 | |
2496 | +// For the ipc transport, zmq permits more than one server to bind to the same endpoint. |
2497 | +// If a server binds to an endpoint while another server is using that endpoint, the |
2498 | +// second server silently "steals" the endpoint from the previous server, so all |
2499 | +// connects after that point go to the new server, while connects that happened earlier |
2500 | +// go to the old server. This is meant as a fail-over feature, and cannot be disabled. |
2501 | +// |
2502 | +// We don't want this and need an error if two servers try to use the same endpoint. |
2503 | +// Hacky solution: we check whether it's possible to successfully connect to the |
2504 | +// endpoint. If so, a server is still running there, and we throw. This has a |
2505 | +// small race because a second server may connect after the check, but before |
2506 | +// the bind. But, in practice, that's good enough for our purposes. |
2507 | + |
2508 | +void safe_bind(zmqpp::socket& s, string const& endpoint) |
2509 | +{ |
2510 | + const std::string transport_prefix = "ipc://"; |
2511 | + if (endpoint.substr(0, transport_prefix.size()) == transport_prefix) |
2512 | + { |
2513 | + string path = endpoint.substr(transport_prefix.size()); |
2514 | + struct sockaddr_un addr; |
2515 | + memset(&addr, 0, sizeof(addr)); |
2516 | + addr.sun_family = AF_UNIX; |
2517 | + strncpy(addr.sun_path, path.c_str(), sizeof(addr.sun_path) - 1); |
2518 | + int fd = ::socket(AF_UNIX, SOCK_STREAM, 0); |
2519 | + if (fd == -1) |
2520 | + { |
2521 | + // LCOV_EXCL_START |
2522 | + throw MiddlewareException("safe_bind(): cannot create socket: " + std::string(strerror(errno))); |
2523 | + // LCOV_EXCL_STOP |
2524 | + } |
2525 | + util::ResourcePtr<int, decltype(&::close)> close_guard(fd, ::close); |
2526 | + if (::connect(fd, (struct sockaddr*)&addr, sizeof(addr)) == 0) |
2527 | + { |
2528 | + // Connect succeeded, so another server is using the socket already. |
2529 | + throw MiddlewareException("safe_bind(): address in use: " + endpoint); |
2530 | + } |
2531 | + } |
2532 | + s.bind(endpoint); |
2533 | +} |
2534 | + |
2535 | } // namespace zmq_middleware |
2536 | |
2537 | } // namespace internal |
2538 | |
2539 | === modified file 'src/scopes/internal/zmq_middleware/ZmqMiddleware.cpp' |
2540 | --- src/scopes/internal/zmq_middleware/ZmqMiddleware.cpp 2014-05-15 08:12:19 +0000 |
2541 | +++ src/scopes/internal/zmq_middleware/ZmqMiddleware.cpp 2014-05-21 14:02:43 +0000 |
2542 | @@ -29,12 +29,14 @@ |
2543 | #include <unity/scopes/internal/zmq_middleware/ReplyI.h> |
2544 | #include <unity/scopes/internal/zmq_middleware/ScopeI.h> |
2545 | #include <unity/scopes/internal/zmq_middleware/StateReceiverI.h> |
2546 | +#include <unity/scopes/internal/zmq_middleware/ZmqPublisher.h> |
2547 | #include <unity/scopes/internal/zmq_middleware/ZmqQuery.h> |
2548 | #include <unity/scopes/internal/zmq_middleware/ZmqQueryCtrl.h> |
2549 | #include <unity/scopes/internal/zmq_middleware/ZmqRegistry.h> |
2550 | #include <unity/scopes/internal/zmq_middleware/ZmqReply.h> |
2551 | #include <unity/scopes/internal/zmq_middleware/ZmqScope.h> |
2552 | #include <unity/scopes/internal/zmq_middleware/ZmqStateReceiver.h> |
2553 | +#include <unity/scopes/internal/zmq_middleware/ZmqSubscriber.h> |
2554 | #include <unity/scopes/internal/zmq_middleware/RethrowException.h> |
2555 | #include <unity/scopes/ScopeExceptions.h> |
2556 | #include <unity/UnityExceptions.h> |
2557 | @@ -59,10 +61,11 @@ |
2558 | namespace |
2559 | { |
2560 | |
2561 | -char const* query_suffix = "-q"; // Appended to server_name_ to create query adapter name |
2562 | -char const* ctrl_suffix = "-c"; // Appended to server_name_ to create control adapter name |
2563 | -char const* reply_suffix = "-r"; // Appended to server_name_ to create reply adapter name |
2564 | -char const* state_suffix = "-s"; // Appended to server_name_ to create state adapter name |
2565 | +char const* query_suffix = "-q"; // Appended to server_name_ to create query adapter name |
2566 | +char const* ctrl_suffix = "-c"; // Appended to server_name_ to create control adapter name |
2567 | +char const* reply_suffix = "-r"; // Appended to server_name_ to create reply adapter name |
2568 | +char const* state_suffix = "-s"; // Appended to server_name_ to create state adapter name |
2569 | +char const* publisher_suffix = "-p"; // Appended to publisher_id to create a publisher endpoint |
2570 | |
2571 | char const* query_category = "Query"; // query adapter category name |
2572 | char const* ctrl_category = "QueryCtrl"; // control adapter category name |
2573 | @@ -657,6 +660,16 @@ |
2574 | return proxy; |
2575 | } |
2576 | |
2577 | +MWPublisher::UPtr ZmqMiddleware::create_publisher(std::string const& publisher_id) |
2578 | +{ |
2579 | + return MWPublisher::UPtr(new ZmqPublisher(&context_, publisher_id + publisher_suffix, config_.public_dir())); |
2580 | +} |
2581 | + |
2582 | +MWSubscriber::UPtr ZmqMiddleware::create_subscriber(std::string const& publisher_id, std::string const& topic) |
2583 | +{ |
2584 | + return MWSubscriber::UPtr(new ZmqSubscriber(&context_, publisher_id + publisher_suffix, config_.public_dir(), topic)); |
2585 | +} |
2586 | + |
2587 | std::string ZmqMiddleware::get_scope_endpoint() |
2588 | { |
2589 | return "ipc://" + config_.private_dir() + "/" + server_name_; |
2590 | |
2591 | === added file 'src/scopes/internal/zmq_middleware/ZmqPublisher.cpp' |
2592 | --- src/scopes/internal/zmq_middleware/ZmqPublisher.cpp 1970-01-01 00:00:00 +0000 |
2593 | +++ src/scopes/internal/zmq_middleware/ZmqPublisher.cpp 2014-05-21 14:02:43 +0000 |
2594 | @@ -0,0 +1,157 @@ |
2595 | +/* |
2596 | + * Copyright (C) 2014 Canonical Ltd |
2597 | + * |
2598 | + * This program is free software: you can redistribute it and/or modify |
2599 | + * it under the terms of the GNU Lesser General Public License version 3 as |
2600 | + * published by the Free Software Foundation. |
2601 | + * |
2602 | + * This program is distributed in the hope that it will be useful, |
2603 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2604 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2605 | + * GNU Lesser General Public License for more details. |
2606 | + * |
2607 | + * You should have received a copy of the GNU Lesser General Public License |
2608 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
2609 | + * |
2610 | + * Authored by: Marcus Tomlinson <marcus.tomlinson@canonical.com> |
2611 | + */ |
2612 | + |
2613 | +#include <unity/scopes/internal/zmq_middleware/ZmqPublisher.h> |
2614 | + |
2615 | +#include <unity/scopes/internal/zmq_middleware/Util.h> |
2616 | +#include <unity/scopes/ScopeExceptions.h> |
2617 | +#include <unity/util/ResourcePtr.h> |
2618 | + |
2619 | +#include <unistd.h> |
2620 | +#include <sys/socket.h> |
2621 | +#include <sys/un.h> |
2622 | + |
2623 | +namespace unity |
2624 | +{ |
2625 | + |
2626 | +namespace scopes |
2627 | +{ |
2628 | + |
2629 | +namespace internal |
2630 | +{ |
2631 | + |
2632 | +namespace zmq_middleware |
2633 | +{ |
2634 | + |
2635 | +ZmqPublisher::ZmqPublisher(zmqpp::context* context, std::string const& publisher_id, |
2636 | + std::string const& endpoint_dir) |
2637 | + : context_(context) |
2638 | + , endpoint_("ipc://" + endpoint_dir + "/" + publisher_id) |
2639 | + , thread_state_(NotRunning) |
2640 | + , thread_exception_(nullptr) |
2641 | +{ |
2642 | + // Validate publisher_id |
2643 | + if (publisher_id.find('/') != std::string::npos) |
2644 | + { |
2645 | + throw MiddlewareException("ZmqPublisher(): A publisher cannot contain a '/' in its id"); |
2646 | + } |
2647 | + |
2648 | + // Start the publisher thread |
2649 | + thread_ = std::thread(&ZmqPublisher::publisher_thread, this); |
2650 | + |
2651 | + std::unique_lock<std::mutex> lock(mutex_); |
2652 | + cond_.wait(lock, [this] { return thread_state_ == Running || thread_state_ == Failed; }); |
2653 | + |
2654 | + if (thread_state_ == Failed) |
2655 | + { |
2656 | + if (thread_.joinable()) |
2657 | + { |
2658 | + thread_.join(); |
2659 | + } |
2660 | + try |
2661 | + { |
2662 | + std::rethrow_exception(thread_exception_); |
2663 | + } |
2664 | + catch (...) |
2665 | + { |
2666 | + throw MiddlewareException("ZmqPublisher(): publisher thread failed to start (endpoint: " + |
2667 | + endpoint_ + ")"); |
2668 | + } |
2669 | + } |
2670 | +} |
2671 | + |
2672 | +ZmqPublisher::~ZmqPublisher() |
2673 | +{ |
2674 | + { |
2675 | + std::lock_guard<std::mutex> lock(mutex_); |
2676 | + thread_state_ = Stopping; |
2677 | + cond_.notify_all(); |
2678 | + } |
2679 | + |
2680 | + if (thread_.joinable()) |
2681 | + { |
2682 | + thread_.join(); |
2683 | + } |
2684 | +} |
2685 | + |
2686 | +std::string ZmqPublisher::endpoint() const |
2687 | +{ |
2688 | + return endpoint_; |
2689 | +} |
2690 | + |
2691 | +void ZmqPublisher::send_message(std::string const& message, std::string const& topic) |
2692 | +{ |
2693 | + std::lock_guard<std::mutex> lock(mutex_); |
2694 | + |
2695 | + // Write message in the format: "<topic>:<message>" |
2696 | + message_queue_.push(topic + ':' + message); |
2697 | + cond_.notify_all(); |
2698 | +} |
2699 | + |
2700 | +void ZmqPublisher::publisher_thread() |
2701 | +{ |
2702 | + try |
2703 | + { |
2704 | + // Create the publisher socket |
2705 | + zmqpp::socket pub_socket(zmqpp::socket(*context_, zmqpp::socket_type::publish)); |
2706 | + pub_socket.set(zmqpp::socket_option::linger, 5000); |
2707 | + safe_bind(pub_socket, endpoint_); |
2708 | + |
2709 | + // Notify constructor that the thread is now running |
2710 | + std::unique_lock<std::mutex> lock(mutex_); |
2711 | + thread_state_ = Running; |
2712 | + cond_.notify_all(); |
2713 | + |
2714 | + // Wait for send_message or stop |
2715 | + while (true) |
2716 | + { |
2717 | + // mutex_ unlocked |
2718 | + cond_.wait(lock, [this] { return thread_state_ == Stopping || !message_queue_.empty(); }); |
2719 | + // mutex_ locked |
2720 | + |
2721 | + // Flush out the message queue before stopping the thread |
2722 | + if (!message_queue_.empty()) |
2723 | + { |
2724 | + pub_socket.send(message_queue_.front()); |
2725 | + message_queue_.pop(); |
2726 | + } |
2727 | + else if (thread_state_ == Stopping) |
2728 | + { |
2729 | + break; |
2730 | + } |
2731 | + } |
2732 | + |
2733 | + // Clean up |
2734 | + pub_socket.close(); |
2735 | + } |
2736 | + catch (...) |
2737 | + { |
2738 | + std::lock_guard<std::mutex> lock(mutex_); |
2739 | + thread_exception_ = std::current_exception(); |
2740 | + thread_state_ = Failed; |
2741 | + cond_.notify_all(); |
2742 | + } |
2743 | +} |
2744 | + |
2745 | +} // namespace zmq_middleware |
2746 | + |
2747 | +} // namespace internal |
2748 | + |
2749 | +} // namespace scopes |
2750 | + |
2751 | +} // namespace unity |
2752 | |
2753 | === added file 'src/scopes/internal/zmq_middleware/ZmqSubscriber.cpp' |
2754 | --- src/scopes/internal/zmq_middleware/ZmqSubscriber.cpp 1970-01-01 00:00:00 +0000 |
2755 | +++ src/scopes/internal/zmq_middleware/ZmqSubscriber.cpp 2014-05-21 14:02:43 +0000 |
2756 | @@ -0,0 +1,185 @@ |
2757 | +/* |
2758 | + * Copyright (C) 2014 Canonical Ltd |
2759 | + * |
2760 | + * This program is free software: you can redistribute it and/or modify |
2761 | + * it under the terms of the GNU Lesser General Public License version 3 as |
2762 | + * published by the Free Software Foundation. |
2763 | + * |
2764 | + * This program is distributed in the hope that it will be useful, |
2765 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2766 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2767 | + * GNU Lesser General Public License for more details. |
2768 | + * |
2769 | + * You should have received a copy of the GNU Lesser General Public License |
2770 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
2771 | + * |
2772 | + * Authored by: Marcus Tomlinson <marcus.tomlinson@canonical.com> |
2773 | + */ |
2774 | + |
2775 | +#include <unity/scopes/internal/zmq_middleware/ZmqSubscriber.h> |
2776 | + |
2777 | +#include <unity/scopes/internal/UniqueID.h> |
2778 | +#include <unity/scopes/internal/zmq_middleware/StopPublisher.h> |
2779 | +#include <unity/scopes/ScopeExceptions.h> |
2780 | + |
2781 | +#include <zmqpp/poller.hpp> |
2782 | +#include <zmqpp/socket.hpp> |
2783 | + |
2784 | +namespace unity |
2785 | +{ |
2786 | + |
2787 | +namespace scopes |
2788 | +{ |
2789 | + |
2790 | +namespace internal |
2791 | +{ |
2792 | + |
2793 | +namespace zmq_middleware |
2794 | +{ |
2795 | + |
2796 | +ZmqSubscriber::ZmqSubscriber(zmqpp::context* context, std::string const& publisher_id, |
2797 | + std::string const& endpoint_dir, std::string const& topic) |
2798 | + : context_(context) |
2799 | + , endpoint_("ipc://" + endpoint_dir + "/" + publisher_id) |
2800 | + , topic_(topic) |
2801 | + , thread_state_(NotRunning) |
2802 | + , thread_exception_(nullptr) |
2803 | + , callback_(nullptr) |
2804 | +{ |
2805 | + // Validate publisher_id |
2806 | + if (publisher_id.find('/') != std::string::npos) |
2807 | + { |
2808 | + throw MiddlewareException("ZmqSubscriber(): A publisher cannot contain a '/' in its id"); |
2809 | + } |
2810 | + |
2811 | + // Start thread_stopper_ publisher (used to send a stop message to the subscriber on destruction) |
2812 | + try |
2813 | + { |
2814 | + UniqueID unique_id; |
2815 | + thread_stopper_.reset(new StopPublisher(context, unique_id.gen())); |
2816 | + } |
2817 | + catch (...) |
2818 | + { |
2819 | + throw MiddlewareException("ZmqSubscriber(): thread_stopper_ failed to initialize (adapter: " + publisher_id + ")"); |
2820 | + } |
2821 | + |
2822 | + // Start the subscriber thread |
2823 | + thread_ = std::thread(&ZmqSubscriber::subscriber_thread, this); |
2824 | + |
2825 | + std::unique_lock<std::mutex> lock(mutex_); |
2826 | + cond_.wait(lock, [this] { return thread_state_ == Running || thread_state_ == Failed; }); |
2827 | + |
2828 | + if (thread_state_ == Failed) |
2829 | + { |
2830 | + if (thread_.joinable()) |
2831 | + { |
2832 | + thread_.join(); |
2833 | + } |
2834 | + try |
2835 | + { |
2836 | + std::rethrow_exception(thread_exception_); |
2837 | + } |
2838 | + catch (...) |
2839 | + { |
2840 | + throw MiddlewareException("ZmqSubscriber(): subscriber thread failed to start (endpoint: " + |
2841 | + endpoint_ + ")"); |
2842 | + } |
2843 | + } |
2844 | +} |
2845 | + |
2846 | +ZmqSubscriber::~ZmqSubscriber() |
2847 | +{ |
2848 | + thread_stopper_->stop(); |
2849 | + |
2850 | + if (thread_.joinable()) |
2851 | + { |
2852 | + thread_.join(); |
2853 | + } |
2854 | +} |
2855 | + |
2856 | +std::string ZmqSubscriber::endpoint() const |
2857 | +{ |
2858 | + return endpoint_; |
2859 | +} |
2860 | + |
2861 | +void ZmqSubscriber::set_message_callback(SubscriberCallback callback) |
2862 | +{ |
2863 | + std::lock_guard<std::mutex> lock(mutex_); |
2864 | + callback_ = callback; |
2865 | +} |
2866 | + |
2867 | +void ZmqSubscriber::subscriber_thread() |
2868 | +{ |
2869 | + try |
2870 | + { |
2871 | + // Subscribe to our associated publisher socket |
2872 | + zmqpp::socket sub_socket(*context_, zmqpp::socket_type::subscribe); |
2873 | + sub_socket.set(zmqpp::socket_option::linger, 0); |
2874 | + sub_socket.connect(endpoint_); |
2875 | + sub_socket.subscribe(topic_); |
2876 | + |
2877 | + // Subscribe to the thread_stopper_ socket |
2878 | + zmqpp::socket stop_socket = thread_stopper_->subscribe(); |
2879 | + |
2880 | + // Configure the message poller |
2881 | + zmqpp::poller poller; |
2882 | + poller.add(sub_socket); |
2883 | + poller.add(stop_socket); |
2884 | + |
2885 | + // Notify constructor that the thread is now running |
2886 | + { |
2887 | + std::lock_guard<std::mutex> lock(mutex_); |
2888 | + thread_state_ = Running; |
2889 | + cond_.notify_all(); |
2890 | + } |
2891 | + |
2892 | + // Poll for messages |
2893 | + std::string message; |
2894 | + while (true) |
2895 | + { |
2896 | + poller.poll(); |
2897 | + |
2898 | + // Flush out the message queue before stopping the thread |
2899 | + if (poller.has_input(sub_socket)) |
2900 | + { |
2901 | + sub_socket.receive(message); |
2902 | + |
2903 | + // Discard the message if no callback is set |
2904 | + std::lock_guard<std::mutex> lock(mutex_); |
2905 | + if (callback_) |
2906 | + { |
2907 | + // Message should arrive in the format: "<topic>:<message>" |
2908 | + if (message.length() > topic_.length() && |
2909 | + message[topic_.length()] == ':') |
2910 | + { |
2911 | + callback_(message.substr(topic_.length() + 1)); |
2912 | + } |
2913 | + } |
2914 | + } |
2915 | + else if(poller.has_input(stop_socket)) |
2916 | + { |
2917 | + break; |
2918 | + } |
2919 | + } |
2920 | + |
2921 | + // Clean up |
2922 | + poller.remove(sub_socket); |
2923 | + poller.remove(stop_socket); |
2924 | + sub_socket.close(); |
2925 | + } |
2926 | + catch (...) |
2927 | + { |
2928 | + std::lock_guard<std::mutex> lock(mutex_); |
2929 | + thread_exception_ = std::current_exception(); |
2930 | + thread_state_ = Failed; |
2931 | + cond_.notify_all(); |
2932 | + } |
2933 | +} |
2934 | + |
2935 | +} // namespace zmq_middleware |
2936 | + |
2937 | +} // namespace internal |
2938 | + |
2939 | +} // namespace scopes |
2940 | + |
2941 | +} // namespace unity |
2942 | |
2943 | === modified file 'test/gtest/scopes/CMakeLists.txt' |
2944 | --- test/gtest/scopes/CMakeLists.txt 2014-05-14 04:50:14 +0000 |
2945 | +++ test/gtest/scopes/CMakeLists.txt 2014-05-21 14:02:43 +0000 |
2946 | @@ -14,7 +14,9 @@ |
2947 | add_subdirectory(IdleShutdown) |
2948 | add_subdirectory(Invocation) |
2949 | add_subdirectory(OptionSelectorFilter) |
2950 | +add_subdirectory(RadioButtonsFilter) |
2951 | add_subdirectory(RangeInputFilter) |
2952 | +add_subdirectory(RatingFilter) |
2953 | add_subdirectory(PreviewWidget) |
2954 | add_subdirectory(QueryMetadata) |
2955 | add_subdirectory(Registry) |
2956 | |
2957 | === modified file 'test/gtest/scopes/Filters/Filters_test.cpp' |
2958 | --- test/gtest/scopes/Filters/Filters_test.cpp 2014-05-08 17:08:38 +0000 |
2959 | +++ test/gtest/scopes/Filters/Filters_test.cpp 2014-05-21 14:02:43 +0000 |
2960 | @@ -18,7 +18,10 @@ |
2961 | |
2962 | #include <unity/scopes/internal/RuntimeImpl.h> |
2963 | #include <unity/scopes/internal/ScopeImpl.h> |
2964 | +#include <unity/scopes/internal/FilterBaseImpl.h> |
2965 | #include <unity/scopes/FilterOption.h> |
2966 | +#include <unity/scopes/RadioButtonsFilter.h> |
2967 | +#include <unity/scopes/RatingFilter.h> |
2968 | #include <unity/scopes/SearchMetadata.h> |
2969 | #include <unity/UnityExceptions.h> |
2970 | #include <gtest/gtest.h> |
2971 | @@ -133,3 +136,72 @@ |
2972 | EXPECT_EQ("o1", option1->id()); |
2973 | } |
2974 | } |
2975 | + |
2976 | +TEST(Filters, deserialize) |
2977 | +{ |
2978 | + // check that FilterBaseImpl::deserialize() creates valid instances of all filter types |
2979 | + { |
2980 | + OptionSelectorFilter::SPtr filter1 = OptionSelectorFilter::create("f1", "Options", false); |
2981 | + auto option1 = filter1->add_option("1", "Option 1"); |
2982 | + auto var = filter1->serialize(); |
2983 | + |
2984 | + auto f = internal::FilterBaseImpl::deserialize(var); |
2985 | + EXPECT_TRUE(std::dynamic_pointer_cast<OptionSelectorFilter const>(f) != nullptr); |
2986 | + EXPECT_EQ("option_selector", f->filter_type()); |
2987 | + |
2988 | + const Filters filters {filter1}; |
2989 | + EXPECT_NO_THROW(internal::FilterBaseImpl::validate_filters(filters)); |
2990 | + } |
2991 | + |
2992 | + { |
2993 | + RadioButtonsFilter::SPtr filter1 = RadioButtonsFilter::create("f1", "Options"); |
2994 | + auto option1 = filter1->add_option("1", "Option 1"); |
2995 | + auto var = filter1->serialize(); |
2996 | + |
2997 | + auto f = internal::FilterBaseImpl::deserialize(var); |
2998 | + EXPECT_TRUE(std::dynamic_pointer_cast<RadioButtonsFilter const>(f) != nullptr); |
2999 | + EXPECT_EQ("radio_buttons", f->filter_type()); |
3000 | + |
3001 | + const Filters filters {filter1}; |
3002 | + EXPECT_NO_THROW(internal::FilterBaseImpl::validate_filters(filters)); |
3003 | + } |
3004 | + |
3005 | + { |
3006 | + RatingFilter::SPtr filter1 = RatingFilter::create("f1", "Options", 5); |
3007 | + auto var = filter1->serialize(); |
3008 | + |
3009 | + auto f = internal::FilterBaseImpl::deserialize(var); |
3010 | + EXPECT_TRUE(std::dynamic_pointer_cast<RatingFilter const>(f) != nullptr); |
3011 | + EXPECT_EQ("rating", f->filter_type()); |
3012 | + |
3013 | + const Filters filters {filter1}; |
3014 | + EXPECT_NO_THROW(internal::FilterBaseImpl::validate_filters(filters)); |
3015 | + } |
3016 | + |
3017 | + { |
3018 | + // invalid data (no filter_type) |
3019 | + VariantMap var; |
3020 | + EXPECT_THROW(internal::FilterBaseImpl::deserialize(var), unity::LogicException); |
3021 | + } |
3022 | +} |
3023 | + |
3024 | +TEST(Filters, validate) |
3025 | +{ |
3026 | + { |
3027 | + FilterBase::SPtr filter1 = OptionSelectorFilter::create("f1", "Options", false); |
3028 | + const Filters filters {filter1}; |
3029 | + EXPECT_THROW(internal::FilterBaseImpl::validate_filters(filters), unity::LogicException); |
3030 | + } |
3031 | + |
3032 | + { |
3033 | + FilterBase::SPtr filter1 = RadioButtonsFilter::create("f1", "Options"); |
3034 | + const Filters filters {filter1}; |
3035 | + EXPECT_THROW(internal::FilterBaseImpl::validate_filters(filters), unity::LogicException); |
3036 | + } |
3037 | + |
3038 | + { |
3039 | + FilterBase::SPtr filter1 = RatingFilter::create("f1", "Options"); |
3040 | + const Filters filters {filter1}; |
3041 | + EXPECT_THROW(internal::FilterBaseImpl::validate_filters(filters), unity::LogicException); |
3042 | + } |
3043 | +} |
3044 | |
3045 | === modified file 'test/gtest/scopes/Filters/TestScope.h' |
3046 | --- test/gtest/scopes/Filters/TestScope.h 2014-03-07 01:07:28 +0000 |
3047 | +++ test/gtest/scopes/Filters/TestScope.h 2014-05-21 14:02:43 +0000 |
3048 | @@ -45,7 +45,7 @@ |
3049 | virtual void run(SearchReplyProxy const& reply) override |
3050 | { |
3051 | Filters filters; |
3052 | - auto filter = OptionSelectorFilter::create("f1", "Choose an option", false); |
3053 | + OptionSelectorFilter::SPtr filter = OptionSelectorFilter::create("f1", "Choose an option", false); |
3054 | filter->add_option("o1", "Option 1"); |
3055 | filter->add_option("o2", "Option 2"); |
3056 | filters.push_back(filter); |
3057 | |
3058 | === modified file 'test/gtest/scopes/IdleShutdown/IdleShutdown_test.cpp' |
3059 | --- test/gtest/scopes/IdleShutdown/IdleShutdown_test.cpp 2014-05-14 04:50:14 +0000 |
3060 | +++ test/gtest/scopes/IdleShutdown/IdleShutdown_test.cpp 2014-05-21 14:02:43 +0000 |
3061 | @@ -40,8 +40,12 @@ |
3062 | { |
3063 | } |
3064 | |
3065 | - virtual void finished(ListenerBase::Reason /* reason */, string const& /* error_message */) override |
3066 | + virtual void finished(ListenerBase::Reason reason, string const& error_message) override |
3067 | { |
3068 | + EXPECT_EQ(ListenerBase::Reason::Error, reason); |
3069 | + EXPECT_EQ("unity::scopes::MiddlewareException: unity::scopes::MiddlewareException: " |
3070 | + "Cannot invoke operations while middleware is stopped", |
3071 | + error_message); |
3072 | lock_guard<mutex> lock(mutex_); |
3073 | query_complete_ = true; |
3074 | cond_.notify_one(); |
3075 | @@ -81,10 +85,10 @@ |
3076 | } |
3077 | |
3078 | // Check that the scope has indeed timed out. The server shuts down after 2 seconds, |
3079 | - // so we allow between 2 and 3 seconds for it to time out. |
3080 | + // so we allow between 2 and 4 seconds for it to time out. |
3081 | auto duration = chrono::steady_clock::now() - start_time; |
3082 | EXPECT_TRUE(duration > chrono::seconds(2)); |
3083 | - EXPECT_TRUE(duration < chrono::seconds(3)); |
3084 | + EXPECT_TRUE(duration < chrono::seconds(4)); |
3085 | } |
3086 | |
3087 | // Check that the idle timeout for a server waits for synchronous operations |
3088 | @@ -122,11 +126,13 @@ |
3089 | |
3090 | // Check that the run time doesn't shut down until |
3091 | // the search in the scope has completed, which takes 4 seconds. |
3092 | - // We allow 4 - 5 seconds for things to shut down before failing |
3093 | - // (or hanging). |
3094 | + // We allow 4 - 6 seconds for things to shut down before failing |
3095 | + // (or hanging). (On Arm, can be slow to shut down, so we allow |
3096 | + // a full two seconds for the server to go away before failing |
3097 | + // the test.) |
3098 | auto duration = chrono::steady_clock::now() - start_time; |
3099 | EXPECT_TRUE(duration > chrono::seconds(4)); |
3100 | - EXPECT_TRUE(duration < chrono::seconds(5)); |
3101 | + EXPECT_TRUE(duration < chrono::seconds(6)); |
3102 | } |
3103 | |
3104 | int main(int argc, char **argv) |
3105 | |
3106 | === modified file 'test/gtest/scopes/IdleShutdown/SlowSearchScope.cpp' |
3107 | --- test/gtest/scopes/IdleShutdown/SlowSearchScope.cpp 2014-05-14 04:50:14 +0000 |
3108 | +++ test/gtest/scopes/IdleShutdown/SlowSearchScope.cpp 2014-05-21 14:02:43 +0000 |
3109 | @@ -64,7 +64,7 @@ |
3110 | |
3111 | SearchQueryBase::UPtr SlowSearchScope::search(CannedQuery const&, SearchMetadata const &) |
3112 | { |
3113 | - this_thread::sleep_for(chrono::seconds(4)); |
3114 | + this_thread::sleep_for(chrono::seconds(4)); |
3115 | return SearchQueryBase::UPtr(new TestQuery()); |
3116 | } |
3117 | |
3118 | |
3119 | === modified file 'test/gtest/scopes/IdleShutdown/Zmq.ini.in' |
3120 | --- test/gtest/scopes/IdleShutdown/Zmq.ini.in 2014-05-14 04:50:14 +0000 |
3121 | +++ test/gtest/scopes/IdleShutdown/Zmq.ini.in 2014-05-21 14:02:43 +0000 |
3122 | @@ -1,3 +1,7 @@ |
3123 | [Zmq] |
3124 | EndpointDir = /tmp |
3125 | -Default.Twoway.Timeout = 5000 |
3126 | +# We set the idle timeout to something much larger than the expected |
3127 | +# time for the test to finish, so we don't see a bogus completion |
3128 | +# of the slow call due to the timeout on the client side triggering, |
3129 | +# rather than the server shutting down. |
3130 | +Default.Twoway.Timeout = 10000 |
3131 | |
3132 | === modified file 'test/gtest/scopes/OptionSelectorFilter/OptionSelectorFilter_test.cpp' |
3133 | --- test/gtest/scopes/OptionSelectorFilter/OptionSelectorFilter_test.cpp 2014-05-15 08:12:32 +0000 |
3134 | +++ test/gtest/scopes/OptionSelectorFilter/OptionSelectorFilter_test.cpp 2014-05-21 14:02:43 +0000 |
3135 | @@ -62,10 +62,12 @@ |
3136 | |
3137 | FilterState fstate; |
3138 | EXPECT_FALSE(fstate.has_filter("f1")); |
3139 | + EXPECT_FALSE(filter1->has_active_option(fstate)); |
3140 | |
3141 | // enable option1 |
3142 | filter1->update_state(fstate, option1, true); |
3143 | EXPECT_TRUE(fstate.has_filter("f1")); |
3144 | + EXPECT_TRUE(filter1->has_active_option(fstate)); |
3145 | auto active = filter1->active_options(fstate); |
3146 | EXPECT_EQ(1u, active.size()); |
3147 | EXPECT_TRUE(active.find(option1) != active.end()); |
3148 | @@ -95,6 +97,7 @@ |
3149 | filter1->update_state(fstate, option1, true); |
3150 | filter1->update_state(fstate, option2, true); |
3151 | EXPECT_TRUE(fstate.has_filter("f1")); |
3152 | + EXPECT_TRUE(filter1->has_active_option(fstate)); |
3153 | auto active = filter1->active_options(fstate); |
3154 | EXPECT_EQ(2u, active.size()); |
3155 | EXPECT_TRUE(active.find(option1) != active.end()); |
3156 | |
3157 | === added directory 'test/gtest/scopes/RadioButtonsFilter' |
3158 | === added file 'test/gtest/scopes/RadioButtonsFilter/CMakeLists.txt' |
3159 | --- test/gtest/scopes/RadioButtonsFilter/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
3160 | +++ test/gtest/scopes/RadioButtonsFilter/CMakeLists.txt 2014-05-21 14:02:43 +0000 |
3161 | @@ -0,0 +1,4 @@ |
3162 | +add_executable(RadioButtonsFilter_test RadioButtonsFilter_test.cpp) |
3163 | +target_link_libraries(RadioButtonsFilter_test ${TESTLIBS}) |
3164 | + |
3165 | +add_test(RadioButtonsFilter RadioButtonsFilter_test) |
3166 | |
3167 | === added file 'test/gtest/scopes/RadioButtonsFilter/RadioButtonsFilter_test.cpp' |
3168 | --- test/gtest/scopes/RadioButtonsFilter/RadioButtonsFilter_test.cpp 1970-01-01 00:00:00 +0000 |
3169 | +++ test/gtest/scopes/RadioButtonsFilter/RadioButtonsFilter_test.cpp 2014-05-21 14:02:43 +0000 |
3170 | @@ -0,0 +1,71 @@ |
3171 | +/* |
3172 | + * Copyright (C) 2014 Canonical Ltd |
3173 | + * |
3174 | + * This program is free software: you can redistribute it and/or modify |
3175 | + * it under the terms of the GNU Lesser General Public License version 3 as |
3176 | + * published by the Free Software Foundation. |
3177 | + * |
3178 | + * This program is distributed in the hope that it will be useful, |
3179 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
3180 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
3181 | + * GNU Lesser General Public License for more details. |
3182 | + * |
3183 | + * You should have received a copy of the GNU Lesser General Public License |
3184 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
3185 | + * |
3186 | + * Authored by: Pawel Stolowski <pawel.stolowski@canonical.com> |
3187 | + */ |
3188 | + |
3189 | +#include <gtest/gtest.h> |
3190 | +#include <unity/scopes/FilterState.h> |
3191 | +#include <unity/scopes/RadioButtonsFilter.h> |
3192 | +#include <unity/UnityExceptions.h> |
3193 | + |
3194 | +using namespace unity::scopes; |
3195 | +using namespace unity::scopes::internal; |
3196 | + |
3197 | +TEST(RadioButtonsFilter, basic) |
3198 | +{ |
3199 | + auto filter1 = RadioButtonsFilter::create("f1", "Choose"); |
3200 | + EXPECT_EQ("f1", filter1->id()); |
3201 | + EXPECT_EQ("Choose", filter1->label()); |
3202 | + EXPECT_EQ(0u, filter1->options().size()); |
3203 | + |
3204 | + filter1->add_option("a", "A"); |
3205 | + filter1->add_option("b", "B"); |
3206 | + |
3207 | + auto opts = filter1->options(); |
3208 | + EXPECT_EQ(2u, opts.size()); |
3209 | + EXPECT_EQ("a", opts.front()->id()); |
3210 | + EXPECT_EQ("A", opts.front()->label()); |
3211 | + EXPECT_EQ("b", opts.back()->id()); |
3212 | + EXPECT_EQ("B", opts.back()->label()); |
3213 | +} |
3214 | + |
3215 | +TEST(RadioButtonsFilter, selection) |
3216 | +{ |
3217 | + auto filter1 = RadioButtonsFilter::create("f1", "Options"); |
3218 | + auto option1 = filter1->add_option("1", "Option 1"); |
3219 | + auto option2 = filter1->add_option("2", "Option 2"); |
3220 | + |
3221 | + FilterState fstate; |
3222 | + EXPECT_FALSE(fstate.has_filter("f1")); |
3223 | + EXPECT_EQ(nullptr, filter1->active_option(fstate)); |
3224 | + EXPECT_FALSE(filter1->has_active_option(fstate)); |
3225 | + |
3226 | + // enable option1 |
3227 | + filter1->update_state(fstate, option1, true); |
3228 | + EXPECT_TRUE(fstate.has_filter("f1")); |
3229 | + auto active = filter1->active_option(fstate); |
3230 | + EXPECT_EQ("1", active->id()); |
3231 | + |
3232 | + // enable option2, option1 get disabled |
3233 | + filter1->update_state(fstate, option2, true); |
3234 | + active = filter1->active_option(fstate); |
3235 | + EXPECT_EQ("2", active->id()); |
3236 | + |
3237 | + // disable option1; filter state remains in the FilterState, just no options are selected |
3238 | + filter1->update_state(fstate, option2, false); |
3239 | + EXPECT_TRUE(fstate.has_filter("f1")); |
3240 | + EXPECT_EQ(nullptr, filter1->active_option(fstate)); |
3241 | +} |
3242 | |
3243 | === added directory 'test/gtest/scopes/RatingFilter' |
3244 | === added file 'test/gtest/scopes/RatingFilter/CMakeLists.txt' |
3245 | --- test/gtest/scopes/RatingFilter/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
3246 | +++ test/gtest/scopes/RatingFilter/CMakeLists.txt 2014-05-21 14:02:43 +0000 |
3247 | @@ -0,0 +1,4 @@ |
3248 | +add_executable(RatingFilter_test RatingFilter_test.cpp) |
3249 | +target_link_libraries(RatingFilter_test ${TESTLIBS}) |
3250 | + |
3251 | +add_test(RatingFilter RatingFilter_test) |
3252 | |
3253 | === added file 'test/gtest/scopes/RatingFilter/RatingFilter_test.cpp' |
3254 | --- test/gtest/scopes/RatingFilter/RatingFilter_test.cpp 1970-01-01 00:00:00 +0000 |
3255 | +++ test/gtest/scopes/RatingFilter/RatingFilter_test.cpp 2014-05-21 14:02:43 +0000 |
3256 | @@ -0,0 +1,111 @@ |
3257 | +/* |
3258 | + * Copyright (C) 2014 Canonical Ltd |
3259 | + * |
3260 | + * This program is free software: you can redistribute it and/or modify |
3261 | + * it under the terms of the GNU Lesser General Public License version 3 as |
3262 | + * published by the Free Software Foundation. |
3263 | + * |
3264 | + * This program is distributed in the hope that it will be useful, |
3265 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
3266 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
3267 | + * GNU Lesser General Public License for more details. |
3268 | + * |
3269 | + * You should have received a copy of the GNU Lesser General Public License |
3270 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
3271 | + * |
3272 | + * Authored by: Pawel Stolowski <pawel.stolowski@canonical.com> |
3273 | + */ |
3274 | + |
3275 | +#include <gtest/gtest.h> |
3276 | +#include <unity/scopes/FilterState.h> |
3277 | +#include <unity/scopes/RatingFilter.h> |
3278 | +#include <unity/UnityExceptions.h> |
3279 | + |
3280 | +using namespace unity::scopes; |
3281 | +using namespace unity::scopes::internal; |
3282 | + |
3283 | +TEST(RatingFilter, basic) |
3284 | +{ |
3285 | + { |
3286 | + auto filter1 = RatingFilter::create("f1", "Rating"); |
3287 | + filter1->set_on_icon("foo"); |
3288 | + filter1->set_off_icon("bar"); |
3289 | + EXPECT_EQ("f1", filter1->id()); |
3290 | + EXPECT_EQ("Rating", filter1->label()); |
3291 | + EXPECT_EQ("foo", filter1->on_icon()); |
3292 | + EXPECT_EQ("bar", filter1->off_icon()); |
3293 | + EXPECT_EQ(0u, filter1->options().size()); |
3294 | + |
3295 | + auto o1 = filter1->add_option("a", "A"); |
3296 | + auto o2 = filter1->add_option("b", "B"); |
3297 | + EXPECT_EQ("a", o1->id()); |
3298 | + EXPECT_EQ("b", o2->id()); |
3299 | + |
3300 | + auto opts = filter1->options(); |
3301 | + EXPECT_EQ(2u, opts.size()); |
3302 | + EXPECT_EQ("a", opts.front()->id()); |
3303 | + EXPECT_EQ("A", opts.front()->label()); |
3304 | + EXPECT_EQ("b", opts.back()->id()); |
3305 | + EXPECT_EQ("B", opts.back()->label()); |
3306 | + } |
3307 | + |
3308 | + { |
3309 | + auto filter1 = RatingFilter::create("f1", "Rating", 3); |
3310 | + EXPECT_EQ("f1", filter1->id()); |
3311 | + EXPECT_EQ("Rating", filter1->label()); |
3312 | + |
3313 | + auto opts = filter1->options(); |
3314 | + EXPECT_EQ(3u, opts.size()); |
3315 | + auto it = opts.begin(); |
3316 | + EXPECT_EQ("1", (*it)->id()); |
3317 | + EXPECT_EQ("1+", (*it)->label()); |
3318 | + EXPECT_EQ("2", (*++it)->id()); |
3319 | + EXPECT_EQ("2+", (*it)->label()); |
3320 | + EXPECT_EQ("3", (*++it)->id()); |
3321 | + EXPECT_EQ("3", (*it)->label()); |
3322 | + } |
3323 | + |
3324 | + { |
3325 | + EXPECT_THROW(RatingFilter::create("f1", "Rating", 11), unity::LogicException); |
3326 | + } |
3327 | + |
3328 | + { |
3329 | + auto filter1 = RatingFilter::create("f1", "Rating", 10); |
3330 | + EXPECT_THROW(filter1->add_option("11", "11"), unity::LogicException); |
3331 | + } |
3332 | +} |
3333 | + |
3334 | +TEST(RatingFilter, selection) |
3335 | +{ |
3336 | + auto filter1 = RatingFilter::create("f1", "Rating", 2); |
3337 | + |
3338 | + FilterState fstate; |
3339 | + EXPECT_FALSE(fstate.has_filter("f1")); |
3340 | + EXPECT_FALSE(filter1->has_active_rating(fstate)); |
3341 | + EXPECT_EQ(nullptr, filter1->active_rating(fstate)); |
3342 | + |
3343 | + auto opts = filter1->options(); |
3344 | + EXPECT_EQ(2u, opts.size()); |
3345 | + |
3346 | + auto it = opts.begin(); |
3347 | + auto option1 = *(it++); |
3348 | + auto option2 = *it; |
3349 | + |
3350 | + // enable option1 |
3351 | + filter1->update_state(fstate, option1, true); |
3352 | + EXPECT_TRUE(fstate.has_filter("f1")); |
3353 | + EXPECT_TRUE(filter1->has_active_rating(fstate)); |
3354 | + auto active = filter1->active_rating(fstate); |
3355 | + EXPECT_EQ("1", active->id()); |
3356 | + |
3357 | + // enable option2, option1 get disabled |
3358 | + filter1->update_state(fstate, option2, true); |
3359 | + active = filter1->active_rating(fstate); |
3360 | + EXPECT_EQ("2", active->id()); |
3361 | + |
3362 | + // disable option1; filter state remains in the FilterState, just no options are selected |
3363 | + filter1->update_state(fstate, option2, false); |
3364 | + EXPECT_TRUE(fstate.has_filter("f1")); |
3365 | + EXPECT_FALSE(filter1->has_active_rating(fstate)); |
3366 | + EXPECT_EQ(nullptr, filter1->active_rating(fstate)); |
3367 | +} |
3368 | |
3369 | === modified file 'test/gtest/scopes/Registry/Registry_test.cpp' |
3370 | --- test/gtest/scopes/Registry/Registry_test.cpp 2014-05-06 04:29:02 +0000 |
3371 | +++ test/gtest/scopes/Registry/Registry_test.cpp 2014-05-21 14:02:43 +0000 |
3372 | @@ -77,25 +77,6 @@ |
3373 | Runtime::UPtr rt = Runtime::create(TEST_RUNTIME_FILE); |
3374 | RegistryProxy r = rt->registry(); |
3375 | |
3376 | - // wait for the registry to become available on middleware |
3377 | - // FIXME: remove this once we have async queries and can set arbitrary timeout when calling registry |
3378 | - const int num_retries = 10; |
3379 | - bool registry_started = false; |
3380 | - for (int i = 0; i < num_retries; ++i) |
3381 | - { |
3382 | - try |
3383 | - { |
3384 | - r->list(); // this will throw if the registry is not yet available on middleware |
3385 | - registry_started = true; |
3386 | - break; |
3387 | - } |
3388 | - catch (std::exception const&) |
3389 | - { |
3390 | - sleep(1); |
3391 | - } |
3392 | - } |
3393 | - ASSERT_TRUE(registry_started); |
3394 | - |
3395 | auto meta = r->get_metadata("testscopeA"); |
3396 | EXPECT_EQ("testscopeA", meta.scope_id()); |
3397 | EXPECT_EQ("Canonical Ltd.", meta.author()); |
3398 | |
3399 | === modified file 'test/gtest/scopes/Registry/Zmq.ini.in' |
3400 | --- test/gtest/scopes/Registry/Zmq.ini.in 2014-05-06 09:00:45 +0000 |
3401 | +++ test/gtest/scopes/Registry/Zmq.ini.in 2014-05-21 14:02:43 +0000 |
3402 | @@ -1,2 +1,3 @@ |
3403 | [Zmq] |
3404 | EndpointDir = /tmp |
3405 | +Default.Twoway.Timeout = 2000 |
3406 | |
3407 | === modified file 'test/gtest/scopes/internal/smartscopes/SmartScopesClient/FakeSss.py' |
3408 | --- test/gtest/scopes/internal/smartscopes/SmartScopesClient/FakeSss.py 2014-05-09 09:56:09 +0000 |
3409 | +++ test/gtest/scopes/internal/smartscopes/SmartScopesClient/FakeSss.py 2014-05-21 14:02:43 +0000 |
3410 | @@ -60,7 +60,7 @@ |
3411 | [{"base_url": "http://127.0.0.1:' + str(port) + '/fail", "id" : "fail.scope", "name": "Fail Scope", "description": "Fails due to no author.", "icon": "icon" },\ |
3412 | {"base_url": "http://127.0.0.1:' + str(port) + '/demo", "id" : "dummy.scope", "name": "Dummy Demo Scope", "description": "Dummy demo scope.", "author": "Mr.Fake", "icon": "icon" },\ |
3413 | {"base_url": "http://127.0.0.1:' + str(port) + '/fail2", "name": "Fail Scope 2", "description": "Fails due to no id.", "author": "Mr.Fake", "icon": "icon" },\ |
3414 | -{"base_url": "http://127.0.0.1:' + str(port) + '/demo2", "id" : "dummy.scope.2", "name": "Dummy Demo Scope 2", "description": "Dummy demo scope 2.", "author": "Mr.Fake", "art": "art", "invisible": true },\ |
3415 | +{"base_url": "http://127.0.0.1:' + str(port) + '/demo2", "id" : "dummy.scope.2", "name": "Dummy Demo Scope 2", "description": "Dummy demo scope 2.", "author": "Mr.Fake", "art": "art", "invisible": true, "appearance": {"background": "#00BEEF"} },\ |
3416 | {"id" : "fail.scope.3", "name": "Fail Scope 3", "description": "Fails due to no base_url.", "author": "Mr.Fake", "art": "art" }]' |
3417 | |
3418 | search_response = '\ |
3419 | |
3420 | === modified file 'test/gtest/scopes/internal/smartscopes/SmartScopesClient/SmartScopesClient_test.cpp' |
3421 | --- test/gtest/scopes/internal/smartscopes/SmartScopesClient/SmartScopesClient_test.cpp 2014-05-09 09:56:09 +0000 |
3422 | +++ test/gtest/scopes/internal/smartscopes/SmartScopesClient/SmartScopesClient_test.cpp 2014-05-21 14:02:43 +0000 |
3423 | @@ -81,6 +81,7 @@ |
3424 | EXPECT_EQ("icon", *scopes[0].icon); |
3425 | EXPECT_EQ(nullptr, scopes[0].art); |
3426 | EXPECT_FALSE(scopes[0].invisible); |
3427 | + EXPECT_EQ(nullptr, scopes[0].appearance); |
3428 | |
3429 | EXPECT_EQ("dummy.scope.2", scopes[1].id); |
3430 | EXPECT_EQ("Dummy Demo Scope 2", scopes[1].name); |
3431 | @@ -90,6 +91,7 @@ |
3432 | EXPECT_EQ(nullptr, scopes[1].icon); |
3433 | EXPECT_EQ("art", *scopes[1].art); |
3434 | EXPECT_TRUE(scopes[1].invisible); |
3435 | + EXPECT_EQ("#00BEEF", (*scopes[1].appearance)["background"].get_string()); |
3436 | } |
3437 | |
3438 | TEST_F(SmartScopesClientTest, search) |
3439 | |
3440 | === modified file 'test/gtest/scopes/internal/zmq_middleware/CMakeLists.txt' |
3441 | --- test/gtest/scopes/internal/zmq_middleware/CMakeLists.txt 2014-04-14 23:47:33 +0000 |
3442 | +++ test/gtest/scopes/internal/zmq_middleware/CMakeLists.txt 2014-05-21 14:02:43 +0000 |
3443 | @@ -1,4 +1,5 @@ |
3444 | add_subdirectory(ObjectAdapter) |
3445 | +add_subdirectory(PubSub) |
3446 | add_subdirectory(RegistryI) |
3447 | add_subdirectory(ServantBase) |
3448 | add_subdirectory(StopPublisher) |
3449 | |
3450 | === modified file 'test/gtest/scopes/internal/zmq_middleware/ObjectAdapter/ObjectAdapter_test.cpp' |
3451 | --- test/gtest/scopes/internal/zmq_middleware/ObjectAdapter/ObjectAdapter_test.cpp 2014-05-02 00:00:08 +0000 |
3452 | +++ test/gtest/scopes/internal/zmq_middleware/ObjectAdapter/ObjectAdapter_test.cpp 2014-05-21 14:02:43 +0000 |
3453 | @@ -1071,8 +1071,7 @@ |
3454 | { |
3455 | EXPECT_STREQ("unity::scopes::MiddlewareException: ObjectAdapter::run_workers(): broker thread failure " |
3456 | "(adapter: testscope):\n" |
3457 | - " unity::scopes::MiddlewareException: ObjectAdapter: broker thread failure " |
3458 | - "(adapter: testscope): address in use: ipc://testscope", e.what()); |
3459 | + " unity::scopes::MiddlewareException: safe_bind(): address in use: ipc://testscope", e.what()); |
3460 | } |
3461 | |
3462 | { |
3463 | @@ -1108,8 +1107,7 @@ |
3464 | { |
3465 | EXPECT_STREQ("unity::scopes::MiddlewareException: ObjectAdapter::run_workers(): broker thread failure " |
3466 | "(adapter: testscope):\n" |
3467 | - " unity::scopes::MiddlewareException: ObjectAdapter: broker thread failure " |
3468 | - "(adapter: testscope): address in use: ipc://testscope", e.what()); |
3469 | + " unity::scopes::MiddlewareException: safe_bind(): address in use: ipc://testscope", e.what()); |
3470 | } |
3471 | |
3472 | { |
3473 | |
3474 | === added directory 'test/gtest/scopes/internal/zmq_middleware/PubSub' |
3475 | === added file 'test/gtest/scopes/internal/zmq_middleware/PubSub/CMakeLists.txt' |
3476 | --- test/gtest/scopes/internal/zmq_middleware/PubSub/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
3477 | +++ test/gtest/scopes/internal/zmq_middleware/PubSub/CMakeLists.txt 2014-05-21 14:02:43 +0000 |
3478 | @@ -0,0 +1,6 @@ |
3479 | +configure_file(Zmq.ini.in Zmq.ini) |
3480 | + |
3481 | +add_executable(PubSub_test PubSub_test.cpp) |
3482 | +target_link_libraries(PubSub_test ${LIBS} ${TESTLIBS}) |
3483 | + |
3484 | +add_test(PubSub PubSub_test) |
3485 | |
3486 | === added file 'test/gtest/scopes/internal/zmq_middleware/PubSub/PubSub_test.cpp' |
3487 | --- test/gtest/scopes/internal/zmq_middleware/PubSub/PubSub_test.cpp 1970-01-01 00:00:00 +0000 |
3488 | +++ test/gtest/scopes/internal/zmq_middleware/PubSub/PubSub_test.cpp 2014-05-21 14:02:43 +0000 |
3489 | @@ -0,0 +1,237 @@ |
3490 | +/* |
3491 | + * Copyright (C) 2014 Canonical Ltd |
3492 | + * |
3493 | + * This program is free software: you can redistribute it and/or modify |
3494 | + * it under the terms of the GNU Lesser General Public License version 3 as |
3495 | + * published by the Free Software Foundation. |
3496 | + * |
3497 | + * This program is distributed in the hope that it will be useful, |
3498 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
3499 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
3500 | + * GNU Lesser General Public License for more details. |
3501 | + * |
3502 | + * You should have received a copy of the GNU Lesser General Public License |
3503 | + * along with this program. If not, see <http://www.gnu.org/lzmqnses/>. |
3504 | + * |
3505 | + * Authored by: Michi Henning <michi.henning@canonical.com> |
3506 | + */ |
3507 | + |
3508 | +#include <scope-api-testconfig.h> |
3509 | +#include <unity/scopes/internal/RuntimeImpl.h> |
3510 | +#include <unity/scopes/internal/zmq_middleware/ZmqMiddleware.h> |
3511 | +#include <unity/scopes/ScopeExceptions.h> |
3512 | + |
3513 | +#include <gtest/gtest.h> |
3514 | +#include <condition_variable> |
3515 | +#include <mutex> |
3516 | + |
3517 | +using namespace std::placeholders; |
3518 | +using namespace unity::scopes; |
3519 | +using namespace unity::scopes::internal; |
3520 | +using namespace unity::scopes::internal::zmq_middleware; |
3521 | + |
3522 | +TEST(PubSub, endpoints) |
3523 | +{ |
3524 | + ZmqMiddleware mw("testscope", (RuntimeImpl*)0x1, |
3525 | + TEST_BUILD_ROOT "/gtest/scopes/internal/zmq_middleware/ObjectAdapter/Zmq.ini"); |
3526 | + |
3527 | + auto publisher = mw.create_publisher("testpublisher"); |
3528 | + auto subscriber = mw.create_subscriber("testpublisher", ""); |
3529 | + |
3530 | + EXPECT_EQ("ipc:///tmp/testpublisher-p", publisher->endpoint()); |
3531 | + EXPECT_EQ(subscriber->endpoint(), publisher->endpoint()); |
3532 | +} |
3533 | + |
3534 | +TEST(PubSub, exceptions) |
3535 | +{ |
3536 | + ZmqMiddleware mw("testscope", (RuntimeImpl*)0x1, |
3537 | + TEST_BUILD_ROOT "/gtest/scopes/internal/zmq_middleware/ObjectAdapter/Zmq.ini"); |
3538 | + |
3539 | + // Test that only one publisher can be created on a single endpoint |
3540 | + auto publisher = mw.create_publisher("testpublisher"); |
3541 | + try |
3542 | + { |
3543 | + auto publisher2 = mw.create_publisher("testpublisher"); |
3544 | + FAIL(); |
3545 | + } |
3546 | + catch (MiddlewareException const& e) |
3547 | + { |
3548 | + EXPECT_STREQ("unity::scopes::MiddlewareException: ZmqPublisher(): publisher thread failed to start " |
3549 | + "(endpoint: ipc:///tmp/testpublisher-p):\n unity::scopes::MiddlewareException: " |
3550 | + "safe_bind(): address in use: ipc:///tmp/testpublisher-p", |
3551 | + e.what()); |
3552 | + } |
3553 | + |
3554 | + // Test that multiple subscribers can be created on a single endpoint |
3555 | + auto subscriber = mw.create_subscriber("testpublisher", ""); |
3556 | + try |
3557 | + { |
3558 | + auto subscriber2 = mw.create_subscriber("testpublisher", "testtopic1"); |
3559 | + auto subscriber3 = mw.create_subscriber("testpublisher", "testtopic2"); |
3560 | + auto subscriber4 = mw.create_subscriber("testpublisher", "testtopic3"); |
3561 | + auto subscriber5 = mw.create_subscriber("testpublisher", "testtopic4"); |
3562 | + } |
3563 | + catch (MiddlewareException const& e) |
3564 | + { |
3565 | + FAIL(); |
3566 | + } |
3567 | + |
3568 | + // Test that an invalid publisher_id throws |
3569 | + try |
3570 | + { |
3571 | + auto publisher2 = mw.create_publisher("/test/"); |
3572 | + FAIL(); |
3573 | + } |
3574 | + catch (MiddlewareException const& e) |
3575 | + { |
3576 | + EXPECT_STREQ("unity::scopes::MiddlewareException: ZmqPublisher(): A publisher cannot contain a '/' in its id", |
3577 | + e.what()); |
3578 | + } |
3579 | + try |
3580 | + { |
3581 | + auto subscriber2 = mw.create_subscriber("/test/", "testtopic"); |
3582 | + FAIL(); |
3583 | + } |
3584 | + catch (MiddlewareException const& e) |
3585 | + { |
3586 | + EXPECT_STREQ("unity::scopes::MiddlewareException: ZmqSubscriber(): A publisher cannot contain a '/' in its id", |
3587 | + e.what()); |
3588 | + } |
3589 | +} |
3590 | + |
3591 | +class SubMsgReceiver |
3592 | +{ |
3593 | +public: |
3594 | + void receive1(std::string const& message) |
3595 | + { |
3596 | + last_sub_index_ = 1; |
3597 | + last_message_ = message; |
3598 | + received(); |
3599 | + } |
3600 | + |
3601 | + void receive2(std::string const& message) |
3602 | + { |
3603 | + last_sub_index_ = 2; |
3604 | + last_message_ = message; |
3605 | + received(); |
3606 | + } |
3607 | + |
3608 | + void receive3(std::string const& message) |
3609 | + { |
3610 | + last_sub_index_ = 3; |
3611 | + last_message_ = message; |
3612 | + received(); |
3613 | + } |
3614 | + |
3615 | + void receive4(std::string const& message) |
3616 | + { |
3617 | + last_sub_index_ = 4; |
3618 | + last_message_ = message; |
3619 | + received(); |
3620 | + } |
3621 | + |
3622 | + void received() |
3623 | + { |
3624 | + // Signal wait_for_message |
3625 | + std::lock_guard<std::mutex> lock(mutex_); |
3626 | + message_received_ = true; |
3627 | + cond_.notify_one(); |
3628 | + } |
3629 | + |
3630 | + bool wait_for_message() |
3631 | + { |
3632 | + std::unique_lock<std::mutex> lock(mutex_); |
3633 | + bool message_received = cond_.wait_for(lock, std::chrono::milliseconds(500), [this] { return this->message_received_; }); |
3634 | + message_received_ = false; |
3635 | + return message_received; |
3636 | + } |
3637 | + |
3638 | + int last_sub_index_ = 0; |
3639 | + std::string last_message_; |
3640 | + |
3641 | + bool message_received_ = false; |
3642 | + std::mutex mutex_; |
3643 | + std::condition_variable cond_; |
3644 | +}; |
3645 | + |
3646 | +TEST(PubSub, send_receive) |
3647 | +{ |
3648 | + SubMsgReceiver message_receiver; |
3649 | + |
3650 | + ZmqMiddleware mw("testscope", (RuntimeImpl*)0x1, |
3651 | + TEST_BUILD_ROOT "/gtest/scopes/internal/zmq_middleware/ObjectAdapter/Zmq.ini"); |
3652 | + |
3653 | + // Create 2 publishers |
3654 | + auto publisher = mw.create_publisher("testpublisher"); |
3655 | + auto publisher2 = mw.create_publisher("testpublisher2"); |
3656 | + |
3657 | + // Create a few subscribers |
3658 | + auto subscriber1 = mw.create_subscriber("testpublisher", "testtopic1"); |
3659 | + subscriber1->set_message_callback(std::bind(&SubMsgReceiver::receive1, &message_receiver, _1)); |
3660 | + |
3661 | + auto subscriber2 = mw.create_subscriber("testpublisher", "testtopic2"); |
3662 | + subscriber2->set_message_callback(std::bind(&SubMsgReceiver::receive2, &message_receiver, _1)); |
3663 | + |
3664 | + auto subscriber3 = mw.create_subscriber("testpublisher", ""); |
3665 | + subscriber3->set_message_callback(std::bind(&SubMsgReceiver::receive3, &message_receiver, _1)); |
3666 | + |
3667 | + auto subscriber4 = mw.create_subscriber("testpublisher2", "testtopic4"); |
3668 | + subscriber4->set_message_callback(std::bind(&SubMsgReceiver::receive4, &message_receiver, _1)); |
3669 | + |
3670 | + // Give the subscribers some time to connect |
3671 | + std::this_thread::sleep_for(std::chrono::milliseconds(500)); |
3672 | + |
3673 | + // Send a "testtopic1" topic message (subscriber1) |
3674 | + publisher->send_message("hello", "testtopic1"); |
3675 | + EXPECT_TRUE(message_receiver.wait_for_message()); |
3676 | + EXPECT_EQ(1, message_receiver.last_sub_index_); |
3677 | + EXPECT_EQ("hello", message_receiver.last_message_); |
3678 | + |
3679 | + // Send a blank "testtopic2" topic message (subscriber2) |
3680 | + publisher->send_message("", "testtopic2"); |
3681 | + EXPECT_TRUE(message_receiver.wait_for_message()); |
3682 | + EXPECT_EQ(2, message_receiver.last_sub_index_); |
3683 | + EXPECT_EQ("", message_receiver.last_message_); |
3684 | + |
3685 | + // Send an empty topic message (subscriber3) |
3686 | + publisher->send_message("hello again!", ""); |
3687 | + EXPECT_TRUE(message_receiver.wait_for_message()); |
3688 | + EXPECT_EQ(3, message_receiver.last_sub_index_); |
3689 | + EXPECT_EQ("hello again!", message_receiver.last_message_); |
3690 | + |
3691 | + // Send a "testtopic4" topic message (subscriber4) |
3692 | + // (no message should be received as subscriber4 is subscribed to a different publisher) |
3693 | + publisher->send_message("test", "testtopic4"); |
3694 | + EXPECT_FALSE(message_receiver.wait_for_message()); |
3695 | + |
3696 | + // Now send a "testtopic4" topic message from the correct publisher (subscriber4) |
3697 | + publisher2->send_message("test", "testtopic4"); |
3698 | + EXPECT_TRUE(message_receiver.wait_for_message()); |
3699 | + EXPECT_EQ(4, message_receiver.last_sub_index_); |
3700 | + EXPECT_EQ("test", message_receiver.last_message_); |
3701 | + |
3702 | + // Send a "unknown" topic message |
3703 | + // (no message should be received as none of the subscribers are listening for "unknown") |
3704 | + publisher->send_message("hello?", "unknown"); |
3705 | + EXPECT_FALSE(message_receiver.wait_for_message()); |
3706 | + |
3707 | + publisher2->send_message("hello??", "unknown"); |
3708 | + EXPECT_FALSE(message_receiver.wait_for_message()); |
3709 | +} |
3710 | + |
3711 | +TEST(PubSub, threading) |
3712 | +{ |
3713 | + ZmqMiddleware mw("testscope", (RuntimeImpl*)0x1, |
3714 | + TEST_BUILD_ROOT "/gtest/scopes/internal/zmq_middleware/ObjectAdapter/Zmq.ini"); |
3715 | + |
3716 | + { |
3717 | + // Create a publisher and a subscriber in seperate thread |
3718 | + auto subscriber_future = std::async(std::launch::async, [&mw]{ return mw.create_subscriber("testpublisher", "testtopic"); }); |
3719 | + auto publisher_future = std::async(std::launch::async, [&mw]{ return mw.create_publisher("testpublisher"); }); |
3720 | + |
3721 | + // Obtain the publisher and subscriber handles |
3722 | + MWSubscriber::UPtr subscriber = subscriber_future.get(); |
3723 | + MWPublisher::UPtr publisher = publisher_future.get(); |
3724 | + } |
3725 | + // The publisher and subscriber are now destroyed in this thread (should not hang / crash) |
3726 | +} |
3727 | |
3728 | === added file 'test/gtest/scopes/internal/zmq_middleware/PubSub/Zmq.ini.in' |
3729 | --- test/gtest/scopes/internal/zmq_middleware/PubSub/Zmq.ini.in 1970-01-01 00:00:00 +0000 |
3730 | +++ test/gtest/scopes/internal/zmq_middleware/PubSub/Zmq.ini.in 2014-05-21 14:02:43 +0000 |
3731 | @@ -0,0 +1,2 @@ |
3732 | +[Zmq] |
3733 | +EndpointDir = /tmp |
3734 | |
3735 | === modified file 'test/gtest/scopes/internal/zmq_middleware/RegistryI/RegistryI_test.cpp' |
3736 | --- test/gtest/scopes/internal/zmq_middleware/RegistryI/RegistryI_test.cpp 2014-05-09 08:51:19 +0000 |
3737 | +++ test/gtest/scopes/internal/zmq_middleware/RegistryI/RegistryI_test.cpp 2014-05-21 14:02:43 +0000 |
3738 | @@ -705,7 +705,7 @@ |
3739 | // check that we still have 1 child process |
3740 | EXPECT_EQ(1, process_count()); |
3741 | |
3742 | - std::this_thread::sleep_for(std::chrono::seconds{2}); |
3743 | + std::this_thread::sleep_for(std::chrono::seconds{3}); |
3744 | |
3745 | // check now that the scope has shutdown automatically (timed out after 2s) |
3746 | EXPECT_FALSE(reg->is_scope_running("testscopeB")); |
FAILED: Continuous integration, rev:349 jenkins. qa.ubuntu. com/job/ unity-scopes- api-ci/ 378/ jenkins. qa.ubuntu. com/job/ unity-scopes- api-utopic- amd64-ci/ 5/console jenkins. qa.ubuntu. com/job/ unity-scopes- api-utopic- armhf-ci/ 5/console jenkins. qa.ubuntu. com/job/ unity-scopes- api-utopic- i386-ci/ 5/console
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/unity- scopes- api-ci/ 378/rebuild
http://