Merge lp:unity-scopes-api/staging into lp:unity-scopes-api

Proposed by Paweł Stołowski
Status: Merged
Approved by: Michi Henning
Approved revision: 311
Merged at revision: 360
Proposed branch: lp:unity-scopes-api/staging
Merge into: lp:unity-scopes-api
Diff against target: 7432 lines (+2810/-1377)
135 files modified
CMakeLists.txt (+1/-1)
CONFIGFILES (+0/-32)
HACKING (+4/-7)
STRUCTS (+15/-4)
debian/VERSION (+1/-1)
debian/changelog (+16/-0)
debian/control (+5/-115)
debian/control.in (+3/-2)
demo/client.cpp (+0/-1)
doc/tutorial.dox (+133/-0)
include/unity/scopes/DateTimePickerFilter.h (+1/-1)
include/unity/scopes/FilterBase.h (+24/-0)
include/unity/scopes/FilterGroup.h (+83/-0)
include/unity/scopes/FilterOption.h (+6/-0)
include/unity/scopes/FilterState.h (+3/-3)
include/unity/scopes/OptionSelectorFilter.h (+34/-4)
include/unity/scopes/RadioButtonsFilter.h (+1/-1)
include/unity/scopes/RangeInputFilter.h (+135/-45)
include/unity/scopes/RatingFilter.h (+2/-2)
include/unity/scopes/SwitchFilter.h (+1/-1)
include/unity/scopes/ValueSliderFilter.h (+38/-59)
include/unity/scopes/ValueSliderLabels.h (+122/-0)
include/unity/scopes/internal/ChildScopesRepository.h (+2/-2)
include/unity/scopes/internal/DfltConfig.h.in (+0/-4)
include/unity/scopes/internal/FilterBaseImpl.h (+9/-1)
include/unity/scopes/internal/FilterGroupImpl.h (+54/-0)
include/unity/scopes/internal/FilterOptionImpl.h (+3/-0)
include/unity/scopes/internal/Logger.h (+87/-69)
include/unity/scopes/internal/OptionSelectorFilterImpl.h (+1/-1)
include/unity/scopes/internal/RangeInputFilterImpl.h (+20/-9)
include/unity/scopes/internal/RatingFilterImpl.h (+4/-1)
include/unity/scopes/internal/RegistryObject.h (+3/-3)
include/unity/scopes/internal/RuntimeConfig.h (+0/-7)
include/unity/scopes/internal/RuntimeImpl.h (+1/-2)
include/unity/scopes/internal/ValueSliderFilterImpl.h (+6/-11)
include/unity/scopes/internal/ValueSliderLabelsImpl.h (+59/-0)
include/unity/scopes/internal/smartscopes/SmartScopesClient.h (+12/-7)
include/unity/scopes/internal/zmq_middleware/ObjectAdapter.h (+1/-2)
include/unity/scopes/internal/zmq_middleware/ZmqMiddleware.h (+1/-1)
scoperegistry/DirWatcher.cpp (+5/-5)
scoperegistry/DirWatcher.h (+2/-2)
scoperegistry/ScopesWatcher.cpp (+14/-15)
scoperegistry/ScopesWatcher.h (+2/-2)
src/scopes/CMakeLists.txt (+2/-0)
src/scopes/CategoryRenderer.cpp (+9/-2)
src/scopes/FilterBase.cpp (+15/-0)
src/scopes/FilterGroup.cpp (+56/-0)
src/scopes/FilterOption.cpp (+5/-0)
src/scopes/OptionSelectorFilter.cpp (+13/-1)
src/scopes/PreviewWidget.cpp (+3/-3)
src/scopes/RangeInputFilter.cpp (+93/-22)
src/scopes/ValueSliderFilter.cpp (+9/-22)
src/scopes/ValueSliderLabels.cpp (+91/-0)
src/scopes/internal/ActivationQueryObject.cpp (+2/-2)
src/scopes/internal/CMakeLists.txt (+2/-0)
src/scopes/internal/ChildScopesRepository.cpp (+13/-22)
src/scopes/internal/FilterBaseImpl.cpp (+59/-2)
src/scopes/internal/FilterGroupImpl.cpp (+97/-0)
src/scopes/internal/FilterOptionImpl.cpp (+12/-1)
src/scopes/internal/Logger.cpp (+146/-221)
src/scopes/internal/OptionSelectorFilterImpl.cpp (+40/-12)
src/scopes/internal/PreviewQueryObject.cpp (+2/-2)
src/scopes/internal/QueryCtrlImpl.cpp (+1/-1)
src/scopes/internal/QueryObject.cpp (+4/-4)
src/scopes/internal/RangeInputFilterImpl.cpp (+102/-30)
src/scopes/internal/RatingFilterImpl.cpp (+1/-1)
src/scopes/internal/RegistryObject.cpp (+31/-41)
src/scopes/internal/ReplyImpl.cpp (+3/-5)
src/scopes/internal/ReplyObject.cpp (+5/-5)
src/scopes/internal/ResultReplyObject.cpp (+9/-1)
src/scopes/internal/RuntimeConfig.cpp (+0/-59)
src/scopes/internal/RuntimeImpl.cpp (+15/-27)
src/scopes/internal/ScopeObject.cpp (+4/-4)
src/scopes/internal/SearchQueryBaseImpl.cpp (+1/-2)
src/scopes/internal/SearchReplyImpl.cpp (+31/-7)
src/scopes/internal/ValueSliderFilterImpl.cpp (+22/-45)
src/scopes/internal/ValueSliderLabelsImpl.cpp (+158/-0)
src/scopes/internal/smartscopes/SSQueryObject.cpp (+2/-2)
src/scopes/internal/smartscopes/SSRegistryObject.cpp (+11/-13)
src/scopes/internal/smartscopes/SSScopeObject.cpp (+2/-2)
src/scopes/internal/smartscopes/SmartScope.cpp (+14/-14)
src/scopes/internal/smartscopes/SmartScopesClient.cpp (+61/-65)
src/scopes/internal/zmq_middleware/ObjectAdapter.cpp (+12/-19)
src/scopes/internal/zmq_middleware/ZmqMiddleware.cpp (+9/-9)
src/scopes/internal/zmq_middleware/ZmqObject.cpp (+2/-2)
test/CMakeLists.txt (+2/-3)
test/abi-compliance/CMakeLists.txt (+10/-6)
test/abi-compliance/abi.xml.in (+0/-57)
test/abi-compliance/check-abi-compliance.sh.in (+61/-21)
test/abi-compliance/gen-abi-dump.sh.in (+2/-2)
test/abi-compliance/suppressions (+36/-0)
test/gtest/scopes/Activation/Runtime.ini.in (+0/-1)
test/gtest/scopes/ActivationResponse/Runtime.ini.in (+0/-1)
test/gtest/scopes/Aggregation/Runtime.ini.in (+0/-1)
test/gtest/scopes/Filters/Filters_test.cpp (+45/-1)
test/gtest/scopes/Filters/Runtime.ini.in (+0/-1)
test/gtest/scopes/Filters/TestScope.h (+2/-1)
test/gtest/scopes/IdleShutdown/Runtime.ini.in (+0/-1)
test/gtest/scopes/Invocation/Runtime.ini.in (+0/-1)
test/gtest/scopes/OptionSelectorFilter/OptionSelectorFilter_test.cpp (+64/-3)
test/gtest/scopes/RangeInputFilter/RangeInputFilter_test.cpp (+115/-55)
test/gtest/scopes/Registry/Runtime.ini.in (+0/-1)
test/gtest/scopes/ReplyReaper/Runtime.ini.in (+0/-1)
test/gtest/scopes/ResultCache/CMakeLists.txt (+1/-1)
test/gtest/scopes/ResultCache/CacheScope.cpp (+14/-2)
test/gtest/scopes/ResultCache/ResultCache_test.cpp (+51/-0)
test/gtest/scopes/ResultCache/Runtime.ini.in (+0/-1)
test/gtest/scopes/Runtime/Runtime.ini.in (+0/-1)
test/gtest/scopes/StripLocation/Runtime.ini.in (+0/-1)
test/gtest/scopes/ThrowingClient/Runtime.ini.in (+0/-1)
test/gtest/scopes/ThrowingScope/Runtime.ini.in (+0/-1)
test/gtest/scopes/ValueSliderFilter/ValueSliderFilter_test.cpp (+71/-33)
test/gtest/scopes/internal/CMakeLists.txt (+2/-1)
test/gtest/scopes/internal/Logger/CMakeLists.txt (+4/-0)
test/gtest/scopes/internal/Logger/Logger_test.cpp (+167/-0)
test/gtest/scopes/internal/ResultReplyObject/Runtime.ini.in (+0/-1)
test/gtest/scopes/internal/RuntimeConfig/BadLogDirSize.ini.in (+0/-7)
test/gtest/scopes/internal/RuntimeConfig/BadLogFileSize.ini.in (+0/-6)
test/gtest/scopes/internal/RuntimeConfig/CacheDir.ini.in (+0/-1)
test/gtest/scopes/internal/RuntimeConfig/Complete.ini.in (+0/-3)
test/gtest/scopes/internal/RuntimeConfig/ConfigDir.ini.in (+0/-1)
test/gtest/scopes/internal/RuntimeConfig/LogDir.ini.in (+0/-5)
test/gtest/scopes/internal/RuntimeConfig/RuntimeConfig_test.cpp (+0/-51)
test/gtest/scopes/internal/RuntimeImpl/Runtime.ini.in (+0/-1)
test/gtest/scopes/internal/ScopeMetadataImpl/Runtime.ini.in (+0/-1)
test/gtest/scopes/internal/smartscopes/SmartScopesClient/FakeSss.py (+10/-0)
test/gtest/scopes/internal/smartscopes/SmartScopesClient/SmartScopesClient_test.cpp (+61/-0)
test/gtest/scopes/internal/smartscopes/smartscopesproxy/Runtime.ini.in (+0/-1)
test/gtest/scopes/internal/zmq_middleware/ObjectAdapter/Runtime.ini.in (+0/-1)
test/gtest/scopes/internal/zmq_middleware/RegistryI/RegistryI_test.cpp (+2/-0)
test/gtest/scopes/internal/zmq_middleware/RegistryI/Runtime.ini.in (+0/-1)
test/gtest/scopes/internal/zmq_middleware/ZmqMiddleware/Runtime.ini.in (+0/-1)
test/gtest/scopes/stress/Runtime.ini.in (+0/-1)
test/gtest/scopes/testing/CMakeLists.txt (+5/-3)
unity-scopes.map (+2/-0)
To merge this branch: bzr merge lp:unity-scopes-api/staging
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Approve
Michi Henning (community) Approve
Review via email: mp+288250@code.launchpad.net

Commit message

Merged devel: use abigail for abi-compoliance checker (disabled for now due o abigail bugs); filters API changes.

Description of the change

Merged devel:
- use abigail for abi-compoliance checker (disabled for now due o abigail bugs).
- filters API changes.

To post a comment you must log in.
Revision history for this message
Michi Henning (michihenning) wrote :

Looks good!

review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
lp:unity-scopes-api/staging updated
312. By Paweł Stołowski

Merged devel

313. By Paweł Stołowski

Merged devel

314. By Paweł Stołowski

Merged devel

315. By Paweł Stołowski

Updated changelog for direct pkg update

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 2015-10-19 04:22:03 +0000
3+++ CMakeLists.txt 2016-03-15 09:18:55 +0000
4@@ -60,7 +60,7 @@
5 endif()
6
7 include(FindPkgConfig)
8-find_package(Boost COMPONENTS system filesystem regex serialization thread log REQUIRED)
9+find_package(Boost COMPONENTS system filesystem regex serialization thread REQUIRED)
10 pkg_check_modules(UNITY_API libunity-api>=0.1.3 REQUIRED)
11 pkg_check_modules(PROCESS_CPP process-cpp>=1.0.1 REQUIRED)
12 pkg_check_modules(APPARMOR REQUIRED libapparmor REQUIRED)
13
14=== modified file 'CONFIGFILES'
15--- CONFIGFILES 2015-12-09 05:43:13 +0000
16+++ CONFIGFILES 2016-03-15 09:18:55 +0000
17@@ -114,38 +114,6 @@
18 The environment variable UNITY_SCOPES_CONFIG_DIR overrides this key (useful when running
19 automated tests that should not overwrite any of the real configuration files).
20
21-- LogDir
22-
23- The parent directory under which the run time writes the scope log files.
24- Setting this value explicitly to the empty string disables file logging and forces
25- all log entries to go to stderr.
26-
27- The default value is the empty string.
28-
29- If you set this value, you must set it to a directory that is writable to
30- confined scopes. We suggest $HOME/.cache/unity-scopes.
31-
32- Note that the actual logs are written into subdirectories of this
33- directory. Assuming LogDir is set to $HOME/.cache/unity-scopes,
34- the subdirectories are
35- $HOME/.cache/unity-scopes/leaf-net/<scope_id>/logs (for confined scopes) and
36- $HOME/.cache/unity-scopes/unconfined/<scope_id>/logs (for unconfined scopes).
37-
38- The environment variable UNITY_SCOPES_LOGDIR overrides this key.
39- Setting this variable explicitly to the empty string disables file logging and forces
40- all log entries to go to stderr.
41-
42-- Log.MaxFileSize
43-
44- The maximum size in bytes of an individual log file before it is rolled over.
45- The value must be at least 1024. The default value is 512 kB.
46-
47-- Log.MaxDirSize
48-
49- The maximum size in bytes of the sum of sizes of all log files in the log directory
50- before they are deleted. The value must be greater than Log.MaxFileSize.
51- The default value is 2 MB.
52-
53 - Log.TraceChannels
54
55 The names of channels for which to emit trace. This must be a semicolon-separated
56
57=== modified file 'HACKING'
58--- HACKING 2015-09-15 21:55:44 +0000
59+++ HACKING 2016-03-15 09:18:55 +0000
60@@ -293,13 +293,13 @@
61 ABI compliance test
62 -------------------
63
64-The tests include an ABI compliance test (for Wily and later). To run it:
65+The tests include an ABI compliance test (for xenial and later). To run it:
66
67 $ cd test/abi-compliance
68 $ make test
69
70 The test is also automatically run as part of the test suite.
71-It takes several minutes to run . If you don't want to wait during local builds,
72+It takes a while to run. If you don't want to wait during local builds,
73 set the cmake "slowtests" option to OFF to skip the check.
74
75 The baseline ABI files for the test are in test/abi-compliance/abi_dumps.
76@@ -313,11 +313,8 @@
77 Once all the packages are built, you can extract the ABI dump
78 files and add them to the corresponding directory in the source tree.
79
80-The abi-compliance-checker tool produces a report in
81-
82- test/abi-compliance/compat_reports/libunity-scopes.so/[version]_to_[version]/compat_report.html
83-
84-The report provides a nicely layed-out page with all the details.
85+The abi compliance test produces a report in
86+libunity-scopes_<current-version>_abi-report.txt if anything unusual is detected.
87
88 Autopkg test suite
89 ------------------
90
91=== modified file 'STRUCTS'
92--- STRUCTS 2015-07-14 15:11:48 +0000
93+++ STRUCTS 2016-03-15 09:18:55 +0000
94@@ -105,6 +105,11 @@
95 =====================================
96 filter_id : Variant (arbitrary, depends on filter type)
97
98+FilterGroup
99+===========
100+ 'id' : string
101+ 'label' : string
102+
103 FilterOption
104 ============
105 'id' : string
106@@ -115,6 +120,7 @@
107 'id' : string
108 'filter_type' : string
109 'display_hints': int, optional
110+ 'filter_group' : string, optional
111
112 OptionSelectorFilter (FilterBase)
113 =================================
114@@ -126,10 +132,15 @@
115
116 RangeInputFilter
117 ================
118- 'id' : string
119- 'start_label' : string
120- 'end_label' : string
121- 'unit_label' : string
122+ 'id' : string
123+ 'default_start_value' : variant (int, double, null)
124+ 'default_end_value' : variant (int, double, null)
125+ 'start_prefix_label' : string
126+ 'start_postfix_label' : string
127+ 'end_prefix_label' : string
128+ 'end_postfix_label' : string
129+ 'central_label' : string
130+ 'filter_group' : string, optional
131
132 Filters + FilterState
133 =====================
134
135=== modified file 'debian/VERSION'
136--- debian/VERSION 2016-02-09 10:26:20 +0000
137+++ debian/VERSION 2016-03-15 09:18:55 +0000
138@@ -1,1 +1,1 @@
139-1.0.3
140+1.0.4
141
142=== modified file 'debian/changelog'
143--- debian/changelog 2016-02-09 15:15:15 +0000
144+++ debian/changelog 2016-03-15 09:18:55 +0000
145@@ -1,3 +1,19 @@
146+unity-scopes-api (1.0.4-0ubuntu1) UNRELEASED; urgency=medium
147+
148+ [ Pawel Stolowski ]
149+ * New RangeInputFilter.
150+
151+ [ Michi Henning ]
152+ * Changed ABI compliance testing to use abigail.
153+
154+ -- Pawel Stolowski <pawel.stolowski@canonical.com> Mon, 11 Jan 2016 12:06:29 +0100
155+
156+unity-scopes-api (1.0.3+16.04.20160209-0ubuntu2) xenial; urgency=medium
157+
158+ * No-change rebuild for zeromq3 transition.
159+
160+ -- Matthias Klose <doko@ubuntu.com> Mon, 14 Mar 2016 22:39:01 +0100
161+
162 unity-scopes-api (1.0.3+16.04.20160209-0ubuntu1) xenial; urgency=medium
163
164 [ Michi Henning ]
165
166=== modified file 'debian/control'
167--- debian/control 2015-12-18 09:21:53 +0000
168+++ debian/control 2016-03-15 09:18:55 +0000
169@@ -1,124 +1,14 @@
170 # This file is autogenerated. DO NOT EDIT!
171-#
172-# Modifications should be made to control.in instead.
173+#
174+# Modifications should be made to debian/control.in instead.
175 # This file is regenerated automatically in the clean target.
176 #
177 Source: unity-scopes-api
178-Priority: optional
179-Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
180-Build-Depends: abi-compliance-checker,
181- capnproto,
182- click-dev (>= 0.2.2),
183- cmake,
184- dbus-test-runner,
185+Maintainer: This not the real control file because it is generated during the build from control.in.
186+Build-Depends: click-dev (>= 0.2.2),
187 debhelper (>= 9),
188- devscripts,
189- doxygen,
190- exuberant-ctags,
191- google-mock,
192- graphviz,
193- libaccounts-glib-dev,
194- libapparmor-dev,
195- libboost-filesystem-dev,
196- libboost-log-dev,
197- libboost-regex-dev,
198- libboost-serialization-dev,
199- libcapnp-dev (>= 0.4.0),
200- libdbustest1-dev,
201- libjsoncpp-dev,
202- liblttng-ust-dev,
203- libnet-cpp-dev (>= 1.2.0),
204- libprocess-cpp-dev (>= 1.0.1),
205- libsignon-glib-dev,
206- libunity-api-dev (>= 7.80.7~),
207- libzmq3-dev,
208- libzmqpp-dev,
209 lsb-release,
210- lttng-tools,
211- pkg-config,
212- python3:any,
213- python-tornado,
214- valgrind,
215-Standards-Version: 3.9.6
216-XS-Testsuite: autopkgtest
217-Section: libs
218-Homepage: https://launchpad.net/unity-scopes-api
219-# if you don't have have commit access to this branch but would like to upload
220-# directly to Ubuntu, don't worry: your changes will be merged back into the
221-# upstream branch
222-Vcs-Bzr: lp:unity-scopes-api
223-Vcs-Browser: https://code.launchpad.net/unity-scopes-api
224
225 Package: libunity-scopes1.0
226 Architecture: any
227-Multi-Arch: same
228-Pre-Depends: ${misc:Pre-Depends},
229-Depends: ${misc:Depends},
230- ${shlibs:Depends},
231-Replaces: libunity-scopes0,
232- libunity-scopes3,
233- libunity-scopes1,
234- libunity-scopes2,
235-Conflicts: libunity-scopes0,
236- libunity-scopes3,
237- libunity-scopes1,
238- libunity-scopes2,
239-Description: API for Unity scopes integration
240- Library to integrate scopes with the Unity shell
241-
242-Package: libunity-scopes-dev
243-Section: libdevel
244-Architecture: any
245-Multi-Arch: same
246-Depends: libproperties-cpp-dev,
247- libunity-api-dev,
248- libunity-scopes1.0 (= ${binary:Version}),
249- ${misc:Depends},
250-Description: Header files for Unity scopes API
251- Library to integrate scopes with the Unity shell (dev files)
252-
253-Package: libunity-scopes-cli
254-Section: devel
255-Architecture: any
256-Multi-Arch: foreign
257-Depends: libunity-scopes1.0 (= ${binary:Version}),
258- ${misc:Depends},
259- ${shlibs:Depends},
260-Description: Client utility for Unity scopes API
261- Commandline client utility for querying Unity scopes, useful for testing.
262-
263-Package: libunity-scopes-doc
264-Section: doc
265-Architecture: all
266-Multi-Arch: foreign
267-Depends: ${misc:Depends},
268-Description: Documentation for Unity scopes API
269- Library to integrate scopes with the Unity shell (documentation)
270-
271-Package: libunity-scopes-qt0.2
272-Architecture: any
273-Multi-Arch: same
274-Pre-Depends: ${misc:Pre-Depends},
275-Depends: ${misc:Depends},
276- ${shlibs:Depends},
277-Description: Qt library for Unity scopes API
278- Library that integrates classes based on Qt for convenience
279-
280-Package: libunity-scopes-qt-dev
281-Section: libdevel
282-Architecture: any
283-Multi-Arch: same
284-Depends: libunity-scopes-dev (= ${binary:Version}),
285- libunity-scopes-qt0.2 (= ${binary:Version}),
286- libnet-cpp-dev (>=1.2.0),
287- ${misc:Depends},
288-Description: Header files for Qt library for Unity scopes API
289- Library that integrates classes based on Qt for convenience (dev files)
290-
291-Package: libunity-scopes-qt-doc
292-Section: doc
293-Architecture: all
294-Multi-Arch: foreign
295-Depends: ${misc:Depends},
296-Description: Documentation for Unity Qt library
297- Library that integrates classes based on Qt for convenience (documentation)
298+Description: This not the real control file because it is generated during the build from control.in.
299
300=== modified file 'debian/control.in'
301--- debian/control.in 2015-11-13 04:05:00 +0000
302+++ debian/control.in 2016-03-15 09:18:55 +0000
303@@ -1,7 +1,8 @@
304 Source: unity-scopes-api
305 Priority: optional
306 Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
307-Build-Depends: abi-compliance-checker,
308+Build-Depends: abigail-tools | libabigail-tools,
309+ binutils,
310 capnproto,
311 click-dev (>= 0.2.2),
312 cmake,
313@@ -15,9 +16,9 @@
314 libaccounts-glib-dev,
315 libapparmor-dev,
316 libboost-filesystem-dev,
317- libboost-log-dev,
318 libboost-regex-dev,
319 libboost-serialization-dev,
320+ libboost-thread-dev,
321 libcapnp-dev (>= 0.4.0),
322 libdbustest1-dev,
323 libjsoncpp-dev,
324
325=== modified file 'demo/client.cpp'
326--- demo/client.cpp 2015-02-09 02:23:22 +0000
327+++ demo/client.cpp 2016-03-15 09:18:55 +0000
328@@ -478,7 +478,6 @@
329 shared_ptr<Receiver> reply(new Receiver(result_index));
330
331 SearchMetadata metadata("C", "desktop");
332- metadata.set_cardinality(10);
333 auto ctrl = meta.proxy()->search(search_string, department_id, filter_state, metadata, reply); // May raise TimeoutException
334 cout << "client: created query" << endl;
335 reply->wait_until_finished();
336
337=== modified file 'doc/tutorial.dox'
338--- doc/tutorial.dox 2015-10-29 02:35:50 +0000
339+++ doc/tutorial.dox 2016-03-15 09:18:55 +0000
340@@ -410,6 +410,75 @@
341 (because `cancelled()` and `run()` are called by different threads and, therefore, can be dispatched out of order).
342
343
344+\paragraph filters Filters
345+
346+Scopes API offers support for filter widgets, which provide means for filtering search results based on user input other than search query string
347+alone. Filter widgets need to be defined by creating appropriate filters inside the overriden SearchQueryBase::run() method, and then pushed
348+to the UI. It is recommended to push filters early before search results are pushed for best user experience.
349+
350+Here is an example of how filters can be created:
351+
352+\code{.cpp}
353+void run(SearchReplyProxy const& reply)
354+{
355+ OptionSelectorFilter::UPtr filter1 = OptionSelectorFilter::create("brand", "Brand");
356+ filter1->add_option("audi", "Audi");
357+ filter1->add_option("bmw", "BMW");
358+
359+ RangeInputFilter::SPtr filter2 = RangeInputFilter::create("price", Variant(0.0f), Variant::null(), "Min", "", "", "Max", "");
360+ ValueSliderFilter::SPtr filter3 = ValueSliderFilter::create("horsepower", 1, 135, 50, ValueSliderLabels("Min", "Max"));
361+
362+ Filters filters;
363+ filters.push_back(filter1);
364+ filters.push_back(filter2);
365+ filters.push_back(filter3);
366+
367+ reply->push(filters, query().filter_state());
368+
369+ // push search results here
370+\endcode
371+
372+Scopes are free to change filters at any time - with every execution of search the scope can omit any of the previously visible filters or add new ones, if that
373+makes sense for particular use cases.
374+
375+Filters act only as UI widgets - it is the responsibility of the scope to check their state and actually apply them to search results. The current value of a filter
376+becomes just another parameter of the search query that needs to be taken into account in the implementation of search handling inside run().
377+
378+To examine current state of the filters, pass the instance of unity::scopes::FilterState received with search query to respective methods of
379+the filters. For example:
380+
381+\code{.cpp}
382+void run(SearchReplyProxy const& reply)
383+{
384+ // filter creation code omitted here
385+ auto state = query().filter_state();
386+ int search_start = 0;
387+ int search_end = 1000;
388+ if (rangefilter->has_start_value(state)) {
389+ search_start = rangefilter->start_value(state);
390+ }
391+ if (rangefilter->has_end_value(state)) {
392+ search_end = rangefilter->end_value(state);
393+ }
394+
395+ // apply search_start and search_end to search logic
396+\endcode
397+
398+The scope may nominate a single filter to act as "primary navigation". This is only possible if departments are not used at the same time (in which case departments
399+become a primary navigation tool). An attempt to nominate a filter to be a "primary navigation" while departments are present is ignored by the UI and the
400+filter acts as a regular filter. Also, only a single-selection OptionSelectorFilter can currently be promoted to be primary navigation. To do this, set the display
401+hints to FilterBase::DisplayHints::Primary:
402+
403+\code{.cpp}
404+OptionSelectorFilter::UPtr filter1 = OptionSelectorFilter::create("brand", "Brand");
405+filter1->set_display_hints(FilterBase::DisplayHints::Primary);
406+filter1->add_option("audi", "Audi");
407+\endcode
408+
409+When a filter becomes a primary navigation filter, it gets displayed in the search box drop-down, below recent searches, so it's readily available for quick access.
410+Also, currently selected option is displayed as a "brick" in the search box, hinting the user about the context of current search. All the other filters can be
411+revealed via the filters panel icon.
412+
413 \paragraph handlingpreview Handling previews
414
415 Your scope is responsible for handling preview requests for results it has returned; you implement this by overriding
416@@ -588,6 +657,70 @@
417 }
418 \endcode
419
420+\paragraph inlineplayback Inline music playback
421+
422+Results which represent music (songs, albums etc.) can contain an extra data about audio content and can then be played directly from the Dash.
423+Such results have a "play" button overlaid on them. To create results that support this functionality two conditions must be met:
424+<ul>
425+<li>Category renderer definition must contain the "quick-preview-type" key with the value of "audio" in the "template" section;
426+<li>Results in the respective category must contain a "quick-preview-data" attribute, each of them is a dictionary with the extra playback data described
427+below.
428+</ul>
429+
430+The data assigned to "quick-preview-data" attribute of a Result needs to contain the following keys:
431+<ul>
432+<li>uri - a playable uri of a media file (path of a local file, or http uri).
433+<li>duration - the duration of the media file, in seconds.
434+<li>playlist - an array of uris of additional songs, e.g. songs from same album; they will be played in sequence when the main
435+song denoted by 'uri' finishes.
436+</ul>
437+
438+Here is an example of a category renderer for inline playback, which uses component mapping to map quick-preview-data to audio-data attribute of a result:
439+\code{.cpp}
440+static const char CATEGORY_RENDERER[] = R"(
441+{
442+ "schema-version": 1,
443+ "template": {
444+ "category-layout": "grid",
445+ "card-size": "large",
446+ "card-layout" : "horizontal",
447+ "quick-preview-type" : "audio"
448+ },
449+ "components": {
450+ "title": "title",
451+ "art": {
452+ "field": "art"
453+ },
454+ "subtitle": "artist",
455+ "quick-preview-data": {
456+ "field": "audio-data"
457+ }
458+ }
459+}
460+)";
461+\endcode
462+
463+A sample code that creates a result card representing a song and all songs from same album in a background playlist may look this way:
464+\code{.cpp}
465+
466+CategorisedResult res(category);
467+res.set_uri(uri);
468+res.set_title(media.getTitle());
469+...
470+
471+VariantMap inline_playback_data;
472+inline_playback_data["uri"] = uri;
473+inline_playback_data["duration"] = song_duration_in_seconds;
474+VariantArray playlist;
475+for (const std::string& song: album_songs)
476+{
477+ playlist.push_back(Variant(song.getUri()));
478+}
479+inline_playback_data["playlist"] = playlist;
480+res["audio-data"] = inline_playback_data;
481+
482+\endcode
483+
484 \subsubsection aggscope Case 2: An aggregating scope
485
486 Aggregating scopes are scopes that collect results from other scopes and possibly consolidate, modify, or re-categorise
487
488=== modified file 'include/unity/scopes/DateTimePickerFilter.h'
489--- include/unity/scopes/DateTimePickerFilter.h 2015-04-02 08:33:56 +0000
490+++ include/unity/scopes/DateTimePickerFilter.h 2016-03-15 09:18:55 +0000
491@@ -77,7 +77,7 @@
492
493 Creates DateTimePickerFilter with given id and mode.
494
495- \param id A unique identifier for the filter that can be used to identify it later among several filters.
496+ \param id A unique identifier for the filter that can be used to later identify it among several filters.
497 \param mode Mode flags that configure values displayed by the filter in the UI.
498 */
499 static DateTimePickerFilter::UPtr create(std::string const& id, Mode mode);
500
501=== modified file 'include/unity/scopes/FilterBase.h'
502--- include/unity/scopes/FilterBase.h 2015-11-12 14:20:36 +0000
503+++ include/unity/scopes/FilterBase.h 2016-03-15 09:18:55 +0000
504@@ -21,6 +21,7 @@
505 #include <unity/util/NonCopyable.h>
506 #include <unity/scopes/Variant.h>
507 #include <unity/util/DefinesPtrs.h>
508+#include <unity/scopes/FilterGroup.h>
509 #include <memory>
510 #include <list>
511
512@@ -94,10 +95,33 @@
513
514 /// @cond
515 virtual ~FilterBase();
516+ /// @endcond
517+
518+ /**
519+ \brief Set an optional title of this filter.
520+ \param title The title.
521+ */
522+ void set_title(std::string const& title);
523+
524+ /**
525+ \brief Get the optional title of this filter.
526+ \return Filter title (can be empty).
527+ */
528+ std::string title() const;
529+
530+ /**
531+ \brief Get the filter group this filter belongs to.
532+
533+ \return The filter group (or null)
534+ */
535+ FilterGroup::SCPtr filter_group() const;
536
537 protected:
538+ /// @cond
539 FilterBase(internal::FilterBaseImpl *pimpl);
540 std::unique_ptr<internal::FilterBaseImpl> p;
541+
542+ friend class internal::FilterBaseImpl;
543 /// @endcond
544 };
545
546
547=== added file 'include/unity/scopes/FilterGroup.h'
548--- include/unity/scopes/FilterGroup.h 1970-01-01 00:00:00 +0000
549+++ include/unity/scopes/FilterGroup.h 2016-03-15 09:18:55 +0000
550@@ -0,0 +1,83 @@
551+/*
552+ * Copyright (C) 2016 Canonical Ltd
553+ *
554+ * This program is free software: you can redistribute it and/or modify
555+ * it under the terms of the GNU Lesser General Public License version 3 as
556+ * published by the Free Software Foundation.
557+ *
558+ * This program is distributed in the hope that it will be useful,
559+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
560+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
561+ * GNU Lesser General Public License for more details.
562+ *
563+ * You should have received a copy of the GNU Lesser General Public License
564+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
565+ *
566+ * Authored by: Pawel Stolowski <pawel.stolowski@canonical.com>
567+ */
568+
569+#pragma once
570+
571+#include <unity/util/NonCopyable.h>
572+#include <unity/util/DefinesPtrs.h>
573+#include <string>
574+#include <memory>
575+
576+namespace unity
577+{
578+
579+namespace scopes
580+{
581+
582+namespace internal
583+{
584+ class FilterGroupImpl;
585+}
586+
587+/**
588+\brief Groups several filters into an expandable widget in the UI.
589+*/
590+class FilterGroup
591+{
592+public:
593+ /// @cond
594+ NONCOPYABLE(FilterGroup);
595+ UNITY_DEFINES_PTRS(FilterGroup);
596+
597+ virtual ~FilterGroup();
598+ /// @endcond
599+
600+ /**
601+ \brief Create a WidgetGroup.
602+
603+ \return An instance of WidgetGroup.
604+ */
605+ static FilterGroup::SCPtr create(std::string const& id, std::string const& label);
606+
607+ /**
608+ \brief Get the id of the widget group.
609+
610+ \return The identifier.
611+ */
612+ std::string id() const;
613+
614+ /**
615+ \brief Get the label of the widget group.
616+
617+ \return The label.
618+ */
619+ std::string label() const;
620+
621+private:
622+ /// @cond
623+ FilterGroup();
624+ FilterGroup(internal::FilterGroupImpl *pimpl);
625+ std::unique_ptr<internal::FilterGroupImpl> p;
626+
627+ friend class internal::FilterGroupImpl;
628+ /// @endcond
629+};
630+
631+} // namespace scopes
632+
633+} // namespace unity
634
635=== modified file 'include/unity/scopes/FilterOption.h'
636--- include/unity/scopes/FilterOption.h 2014-11-03 05:31:30 +0000
637+++ include/unity/scopes/FilterOption.h 2016-03-15 09:18:55 +0000
638@@ -62,6 +62,12 @@
639 ~FilterOption();
640 /// @endcond
641
642+ /**
643+ \brief Return the default value of this filter option.
644+ \return The default value.
645+ */
646+ bool default_value() const;
647+
648 private:
649 FilterOption(std::string const& id, std::string const& label);
650 std::unique_ptr<internal::FilterOptionImpl> p;
651
652=== modified file 'include/unity/scopes/FilterState.h'
653--- include/unity/scopes/FilterState.h 2015-01-09 03:02:47 +0000
654+++ include/unity/scopes/FilterState.h 2016-03-15 09:18:55 +0000
655@@ -37,10 +37,10 @@
656 }
657
658 /**
659-\brief Captures state of multiple filters.
660+\brief Stores the state of multiple filters.
661
662-State can be examined by passing an instance of FilterState to
663-appropriate methods of filters (FilterBase implementations).
664+The state can be examined by passing an instance of FilterState to
665+the appropriate methods of classes derived from FilterBase.
666 */
667
668 class FilterState final
669
670=== modified file 'include/unity/scopes/OptionSelectorFilter.h'
671--- include/unity/scopes/OptionSelectorFilter.h 2015-11-12 14:20:36 +0000
672+++ include/unity/scopes/OptionSelectorFilter.h 2016-03-15 09:18:55 +0000
673@@ -21,6 +21,7 @@
674 #include <unity/scopes/FilterBase.h>
675 #include <unity/scopes/FilterOption.h>
676 #include <unity/scopes/Variant.h>
677+#include <unity/scopes/FilterGroup.h>
678 #include <string>
679 #include <list>
680 #include <set>
681@@ -51,7 +52,7 @@
682
683 /**
684 \brief Creates an OpionSelectorFilter.
685- \param id A unique identifier for the filter that can be used to identify it later among several filters.
686+ \param id A unique identifier for the filter that can be used to later identify it among several filters.
687 \param label A display label for the filter.
688 \param multi_select If true, the filter permits more than option to be selected; otherwise, only a single
689 option can be selected.
690@@ -74,7 +75,9 @@
691 bool multi_select() const;
692
693 /**
694- \brief Add a new option to this filter.
695+ \brief Add a new option to this filter. The option is 'off' by default.
696+
697+ \throws unity::InvalidArgumentException on invalid id or label
698 \return The new option instance.
699 */
700 FilterOption::SCPtr add_option(std::string const& id, std::string const& label);
701@@ -93,8 +96,12 @@
702 bool has_active_option(FilterState const& filter_state) const;
703
704 /**
705- \brief Get active options from an instance of FilterState for this filter.
706- \return The set of selected filter options.
707+ \brief Get the active options from a FilterState instance for this filter.
708+
709+ The returned set may be empty if the user de-selected all options. However, if there is no state
710+ recorded for this filter in the filter_state instance, then all the options enabled by default are returned.
711+
712+ \return The set of selected filter options (or options enabled by default if the filter is not present in the filter_state).
713 */
714 std::set<FilterOption::SCPtr> active_options(FilterState const& filter_state) const;
715
716@@ -114,6 +121,29 @@
717 */
718 static void update_state(FilterState& filter_state, std::string const& filter_id, std::string const& option_id, bool value);
719
720+ /**
721+ \brief Add a new option to this filter and provide its default value.
722+
723+ \throws unity::LogicException if multiple options with value of 'true' are provided for a single-selection OptionSelectorFilter.
724+ \throws unity::InvalidArgumentException on invalid id or label
725+ \return The new option instance.
726+ */
727+ FilterOption::SCPtr add_option(std::string const& id, std::string const& label, bool value);
728+
729+ /**
730+ \brief Creates an OpionSelectorFilter inside a FilterGroup.
731+ \param id A unique identifier for the filter that can be used to later identify it among several filters.
732+ \param label A display label for the filter.
733+ \param group A filter group this filter should be added to.
734+ \param multi_select If true, the filter permits more than option to be selected; otherwise, only a single
735+ option can be selected.
736+ \throws unity::InvalidArgumentException on invalid null group.
737+
738+ \note The multi-selection cannot be combined with unity::scopes::FilterBase::DisplayHints::Primary flag set via
739+ unity::scopes::FilterBase::set_display_hints().
740+ */
741+ static OptionSelectorFilter::UPtr create(std::string const& id, std::string const& label, FilterGroup::SCPtr const& group, bool multi_select = false);
742+
743 private:
744 OptionSelectorFilter(internal::OptionSelectorFilterImpl*);
745 internal::OptionSelectorFilterImpl* fwd() const;
746
747=== modified file 'include/unity/scopes/RadioButtonsFilter.h'
748--- include/unity/scopes/RadioButtonsFilter.h 2014-11-03 05:31:30 +0000
749+++ include/unity/scopes/RadioButtonsFilter.h 2016-03-15 09:18:55 +0000
750@@ -55,7 +55,7 @@
751 \brief Creates RadioButtonsFilter filter.
752
753 Creates an empty RadioButtonsFilter filter. Use unity::scopes::RadioButtonsFilter::add_option() to add options to it.
754- \param id A unique identifier for the filter that can be used to identify it later among several filters.
755+ \param id A unique identifier for the filter that can be used to later identify it among several filters.
756 \param label A display label for this filter
757 \return Instance of RadioButtonsFilter
758 */
759
760=== modified file 'include/unity/scopes/RangeInputFilter.h'
761--- include/unity/scopes/RangeInputFilter.h 2014-11-03 05:31:30 +0000
762+++ include/unity/scopes/RangeInputFilter.h 2016-03-15 09:18:55 +0000
763@@ -1,5 +1,5 @@
764 /*
765- * Copyright (C) 2014 Canonical Ltd
766+ * Copyright (C) 2015 Canonical Ltd
767 *
768 * This program is free software: you can redistribute it and/or modify
769 * it under the terms of the GNU Lesser General Public License version 3 as
770@@ -20,6 +20,7 @@
771
772 #include <unity/scopes/FilterBase.h>
773 #include <unity/scopes/Variant.h>
774+#include <unity/scopes/FilterGroup.h>
775
776 namespace unity
777 {
778@@ -34,11 +35,14 @@
779 class RangeInputFilterImpl;
780 }
781
782-namespace experimental
783-{
784-
785 /**
786-\brief A range filter which allows a start and end value to be entered by user, and any of them is optional.
787+\brief A range filter allows a start and end value to be entered by the user.
788+
789+A RangeInputFilter is composed of two input boxes that accept numeric values (both of them optional).
790+The filter can have prefix and/or postfix labels for the start and end value, respectively, plus a single
791+label that is displayed between the two input boxes.
792+The filter can provide defaults for that start and end value, which are used by the UI if the user does not
793+enter explicit values.
794 */
795 class UNITY_API RangeInputFilter : public FilterBase
796 {
797@@ -49,37 +53,128 @@
798
799 /**
800 \brief Creates a RangeInputFilter.
801- \param id A unique identifier for the filter that can be used to identify it later among several filters.
802- \param start_label A display label for the input box of start value (can be empty).
803- \param end_label A display label for the input box of end value (can be empty).
804- \param unit_label A display label for the unit of this range filter (e.g. currency name).
805- \return Instance of RangeInputFilter.
806- */
807- static RangeInputFilter::SPtr create(std::string const& id, std::string const& start_label, std::string const& end_label, std::string const& unit_label = "");
808-
809- /**
810- \brief Get the label of start value.
811- \return The label of start value.
812- */
813- std::string start_label() const;
814-
815- /**
816- \brief Get the label of end value.
817- \return The label of end value.
818- */
819- std::string end_label() const;
820-
821- /**
822- \brief Get the label of unit for this filter..
823- \return The label of unit.
824- */
825- std::string unit_label() const;
826+ \param id A unique identifier for the filter that can be used to later identify it among several filters.
827+ \param start_prefix_label A display label for the input box for the start value, displayed to the left (can be empty).
828+ \param start_postfix_label A display label for the input box for the start value, displayed to the right (can be empty).
829+ \param central_label A display label that is displayed between the two input boxes (can be empty).
830+ \param end_prefix_label A display label for the input box for the end value, displayed to the left (can be empty).
831+ \param end_postfix_label A display label for the input box for the end value, displayed to the right (can be empty).
832+ \return Instance of RangeInputFilter.
833+ */
834+ static RangeInputFilter::SPtr create(std::string const& id,
835+ std::string const& start_prefix_label, std::string const& start_postfix_label,
836+ std::string const& central_label,
837+ std::string const& end_prefix_label, std::string const& end_postfix_label);
838+
839+ /**
840+ \brief Creates a RangeInputFilter with specific default values for start and end.
841+ \param id A unique identifier for the filter that can be used to later identify it among several filters.
842+ \param default_start_value A default start value (double, int, or null).
843+ \param default_end_value A default end value (double, int, or null).
844+ \param start_prefix_label A display label for the input box for the start value, displayed to the left (can be empty).
845+ \param start_postfix_label A display label for the input box for the start value, displayed to the right (can be empty).
846+ \param central_label A display label displayed between the two input boxes (can be empty).
847+ \param end_prefix_label A display label for the input box for the end value, displayed to the left (can be empty).
848+ \param end_postfix_label A display label for the input box for the end value, displayed to the right (can be empty).
849+ \return Instance of RangeInputFilter.
850+ */
851+ static RangeInputFilter::SPtr create(std::string const& id,
852+ Variant const& default_start_value,
853+ Variant const& default_end_value,
854+ std::string const& start_prefix_label, std::string const& start_postfix_label,
855+ std::string const& central_label,
856+ std::string const& end_prefix_label, std::string const& end_postfix_label);
857+
858+ /**
859+ \brief Creates a RangeInputFilter inside a FilterGroup.
860+ \param id A unique identifier for the filter that can be used to later identify it among several filters.
861+ \param start_prefix_label A display label for the input box for the start value, displayed to the left (can be empty).
862+ \param start_postfix_label A display label for the input box for the start value, displayed to the right (can be empty).
863+ \param central_label A display label displayed between the two input boxes (can be empty).
864+ \param end_prefix_label A display label for the input box for the end value, displayed to the left (can be empty).
865+ \param end_postfix_label A display label for the input box for the end value, displayed to the right (can be empty).
866+ \param group A filter group this filter should be added to.
867+ \return Instance of RangeInputFilter.
868+ */
869+ static RangeInputFilter::SPtr create(std::string const& id,
870+ std::string const& start_prefix_label, std::string const& start_postfix_label,
871+ std::string const& central_label,
872+ std::string const& end_prefix_label, std::string const& end_postfix_label, FilterGroup::SCPtr const& group);
873+
874+ /**
875+ \brief Creates a RangeInputFilter with specific default values for start and end, inside a FilterGroup.
876+ \param id A unique identifier for the filter that can be used to later identify it among several filters.
877+ \param default_start_value The default start value (double, int, or null).
878+ \param default_end_value The default end value (double, int, or null).
879+ \param start_prefix_label A display label for the input box for the start value, displayed to the left (can be empty).
880+ \param start_postfix_label A display label for the input box for the start value, displayed to the right (can be empty).
881+ \param central_label A display label displayed between the two input boxes (can be empty).
882+ \param end_prefix_label A display label for the input box for the end value, displayed to the left (can be empty).
883+ \param end_postfix_label A display label for the input box for the end value, displayed to the right (can be empty).
884+ \param group A filter group this filter should be added to.
885+ \return Instance of RangeInputFilter.
886+ */
887+ static RangeInputFilter::SPtr create(std::string const& id,
888+ Variant const& default_start_value,
889+ Variant const& default_end_value,
890+ std::string const& start_prefix_label, std::string const& start_postfix_label,
891+ std::string const& central_label,
892+ std::string const& end_prefix_label, std::string const& end_postfix_label,
893+ FilterGroup::SCPtr const& group);
894+
895+ /**
896+ \brief Get the prefix label of start value.
897+ \return The prefix label of start value.
898+ */
899+ std::string start_prefix_label() const;
900+
901+ /**
902+ \brief Get the postfix label of start value.
903+ \return The postfix label of start value.
904+ */
905+ std::string start_postfix_label() const;
906+
907+ /**
908+ \brief Get the prefix label of end value.
909+ \return The prefix label of end value.
910+ */
911+ std::string end_prefix_label() const;
912+
913+ /**
914+ \brief Get the postfix label of end value.
915+ \return The postfix label of end value.
916+ */
917+ std::string end_postfix_label() const;
918+
919+ /**
920+ \brief Get the central label for this filter.
921+ \return The central label.
922+ */
923+ std::string central_label() const;
924+
925+ /**
926+ \brief Get the default start value if set (int, double or null).
927+
928+ The default value should be used unless a value is present in the FilterState -
929+ use unity::scopes::RangeInputFilter::has_start_value() and unity::scopes::RangeInputFilter::start_value()
930+ before resorting to the default value.
931+ */
932+ Variant default_start_value() const;
933+
934+ /**
935+ \brief Get default end value if set (int, double or null).
936+
937+ The default value should be used unless a value is present in the FilterState -
938+ use unity::scopes::RangeInputFilter::has_end_value() and unity::scopes::RangeInputFilter::end_value()
939+ before resorting to the default value.
940+ */
941+ Variant default_end_value() const;
942
943 /**
944 \brief Check if filter state holds a start value for this filter instance.
945
946 \param filter_state The state of filters.
947- \return true if filter_state has a start value for this filter.
948+ \return `true` if filter_state has a start value for this filter.
949 */
950 bool has_start_value(FilterState const& filter_state) const;
951
952@@ -87,23 +182,23 @@
953 \brief Check if filter state holds an end value for this filter instance.
954
955 \param filter_state The state of filters.
956- \return true if filter_state has an end value for this filter.
957+ \return `true` if filter_state has an end value for this filter.
958 */
959 bool has_end_value(FilterState const& filter_state) const;
960
961 /**
962- \brief Get start value for this filter instance.
963+ \brief Get the start value for this filter instance.
964
965- \return The start value.
966- \throws unity::scopes::NotFoundException if start value is not set.
967+ \return The start value or the default start value if not null.
968+ \throws unity::scopes::NotFoundException if the start value is not set and the default start value is null.
969 */
970 double start_value(FilterState const& filter_state) const;
971
972 /**
973 \brief Get end value for this filter instance.
974
975- \return The end value.
976- \throws unity::scopes::NotFoundException if end value is not set.
977+ \return The end value or the default end value if not null.
978+ \throws unity::scopes::NotFoundException if the end value is not set and the default end value is null.
979 */
980 double end_value(FilterState const& filter_state) const;
981
982@@ -111,9 +206,9 @@
983 \brief Store start and end value for this filter in the filter state.
984
985 Updates filter_state with start and end values for this filter instance. Allowed data types for start_value and end_value
986- are Variant::Type::Null, Variant::Type::Double and Variant::Type::Int. Integer values will get converted to double when
987+ are Variant::Type::Null, Variant::Type::Double and Variant::Type::Int. Integer values are converted to double when
988 returned via unity::scopes::RangeInputFilter::start_value() and unity::scopes::RangeInputFilter::end_value() methods.
989- Pass Variant::null() as start_value or end_value if that value is unspecified (hasn't been entered or got erased by the user
990+ Pass Variant::null() as start_value or end_value if that value is unspecified (hasn't been entered or was erased by the user
991 from the input box).
992
993 \param filter_state FilterState instance to update
994@@ -126,10 +221,7 @@
995 \brief Store start and end value in the filter state, without having an instance of RangeInputFilter.
996
997 Updates filter_state with start and end values without an instance of RangeInputFilter. This is meant
998- for the explanation of this method.
999- to be used when creating a CannedQuery that points to a foreign scope.
1000-
1001- See the documentation of unity::scopes::update_state(FilterState const& filter_state, Variant const& start_value, Variant const& end_value)
1002+ to be used when creating a CannedQuery that references another scope.
1003
1004 \param filter_state FilterState instance to update
1005 \param filter_id Unique identifier of filter
1006@@ -144,8 +236,6 @@
1007 friend class internal::RangeInputFilterImpl;
1008 };
1009
1010-} // namespace experimental
1011-
1012 } // namespace scopes
1013
1014 } // namespace unity
1015
1016=== modified file 'include/unity/scopes/RatingFilter.h'
1017--- include/unity/scopes/RatingFilter.h 2014-11-03 05:31:30 +0000
1018+++ include/unity/scopes/RatingFilter.h 2016-03-15 09:18:55 +0000
1019@@ -60,7 +60,7 @@
1020 \brief Creates RatingFilter widget.
1021
1022 Creates an empty RatingFilter widget. Use unity::scopes::RatingFilter::add_option() to add rating options to it.
1023- \param id A unique identifier for the filter that can be used to identify it later among several filters.
1024+ \param id A unique identifier for the filter that can be used to later identify it among several filters.
1025 \param label A display label for this filter
1026 \return Instance of RatingFilter
1027 */
1028@@ -75,7 +75,7 @@
1029 "1+", "2+" etc., except for that last label, which is just the number (no plus sign). The maximum top_rating
1030 allowed is 10.
1031
1032- \param id A unique identifier for the filter that can be used to identify it later among several filters.
1033+ \param id A unique identifier for the filter that can be used to later identify it among several filters.
1034 \param label A display label for this filter
1035 \param top_rating The maximum rating allowed.
1036 \return Instance of RatingFilter
1037
1038=== modified file 'include/unity/scopes/SwitchFilter.h'
1039--- include/unity/scopes/SwitchFilter.h 2014-11-03 05:31:30 +0000
1040+++ include/unity/scopes/SwitchFilter.h 2016-03-15 09:18:55 +0000
1041@@ -50,7 +50,7 @@
1042
1043 /**
1044 \brief Creates a SwitchFilter
1045- \param id A unique identifier for the filter that can be used to identify it later among several filters.
1046+ \param id A unique identifier for the filter that can be used to later identify it among several filters.
1047 \param label A display label for the filter.
1048 \return SwitchFilter instance
1049 */
1050
1051=== modified file 'include/unity/scopes/ValueSliderFilter.h'
1052--- include/unity/scopes/ValueSliderFilter.h 2014-11-03 05:31:30 +0000
1053+++ include/unity/scopes/ValueSliderFilter.h 2016-03-15 09:18:55 +0000
1054@@ -19,6 +19,7 @@
1055 #pragma once
1056
1057 #include <unity/scopes/FilterBase.h>
1058+#include <unity/scopes/FilterGroup.h>
1059
1060 namespace unity
1061 {
1062@@ -33,16 +34,14 @@
1063 class ValueSliderFilterImpl;
1064 }
1065
1066-namespace experimental
1067-{
1068+class ValueSliderLabels;
1069
1070 /**
1071-\brief A value slider filter that allows for selecting a value within given range.
1072+\brief A value slider filter that allows for selecting a value within a given range.
1073
1074-The ValueSliderFilter displays a static label, such as "Maximum size" and a slider that
1075-allows for selecting a value within range defined by minimum and maximum values. The currently
1076-selected value gets displayed using a label template provided by scope, e.g. "Less than %1 MB",
1077-resulting in labels such as "Less than 40.5 MB".
1078+The ValueSliderFilter allows for selecting a value within a range defined by minimum and maximum values.
1079+Both minimum and maximum values can have labels and, in addition, the scope may provide extra labels
1080+to mark other values from that range - these label will serve as a guidance to the user.
1081 */
1082 class UNITY_API ValueSliderFilter : public FilterBase
1083 {
1084@@ -52,62 +51,52 @@
1085 /// @endcond
1086
1087 /**
1088- \brief The type of value slider.
1089-
1090- The type should be set according to the behaviour of the filter:
1091- ValueSliderFilter::SliderType::LessThan should be used if values lesser than selected value are to be returned, otherwise
1092- ValueSliderFilter::SliderType::MoreThan should be used.
1093- Note: the selected type is a display hint for the Shell only. It's up to the scope to set it properly and actually follow
1094- it on search.
1095- */
1096- enum SliderType
1097- {
1098- LessThan, /**< Scope will search for values lesser than selected value */
1099- MoreThan /**< Scope will search for values greater than selected value */
1100- };
1101-
1102- /**
1103 \brief Create ValueSliderFilter.
1104
1105 Creates ValueSliderFilter of ValueSliderFilter::SliderType::LessThan type.
1106
1107- \param id A unique identifier for the filter that can be used to identify it later among several filters.
1108- \param label The label for the filter
1109- \param label_template The template for value label, e.g. "Less than %1"
1110+ \param id A unique identifier for the filter that can be used to later identify it among several filters.
1111 \param min The minimum allowed value
1112 \param max The maximum allowed value
1113+ \param default_value The default value of this filter, from the min..max range.
1114+ \param value_labels The labels for min and max values as well as optional extra labels.
1115 \return Instance of ValueSliderFilter.
1116- \throws unity::LogicException on invalid (min, max) range.
1117+ \throws unity::LogicException on invalid (min, max) range or erroneous value_labels.
1118 */
1119- static ValueSliderFilter::UPtr create(std::string const& id, std::string const& label, std::string const& label_template, double min, double max);
1120+ static ValueSliderFilter::UPtr create(std::string const& id, double min, double max, double default_value, ValueSliderLabels const& value_labels);
1121
1122 /**
1123- \brief Change the type of this filter.
1124-
1125- \param tp The type of slider filter.
1126- */
1127- void set_slider_type(SliderType tp);
1128+ \brief Create ValueSliderFilter inside a FilterGroup.
1129+
1130+ Creates ValueSliderFilter of ValueSliderFilter::SliderType::LessThan type.
1131+
1132+ \param id A unique identifier for the filter that can be used to later identify it among several filters.
1133+ \param min The minimum allowed value
1134+ \param max The maximum allowed value
1135+ \param default_value The default value of this filter, from the min..max range.
1136+ \param value_labels The labels for min and max values as well as optional extra labels.
1137+ \param group A filter group this filter should be added to.
1138+ \return Instance of ValueSliderFilter.
1139+ \throws unity::LogicException on invalid (min, max) range or erroneous value_labels.
1140+ */
1141+ static ValueSliderFilter::UPtr create(std::string const& id, double min, double max, double default_value, ValueSliderLabels const& value_labels, FilterGroup::SCPtr const& group);
1142
1143 /**
1144 \brief Change the default value of this filter.
1145
1146- The default value of this filter is by default the maximum value allowed. This value is used when calling unity::scopes::ValueSliderFilter::value_label()
1147- and there is no state for this filter in unity::scopes::FilterState.
1148+ The default value will be used by the shell if no value is present for this filter in the
1149+ unity::scopes::FilterState (no value has been set by the user).
1150
1151 \param val The new default value.
1152 */
1153 void set_default_value(double val);
1154
1155 /**
1156- \brief Get the type of this filter.
1157-
1158- \return The type of slider filter.
1159- */
1160- SliderType slider_type() const;
1161-
1162- /**
1163 \brief Get the default value of this filter.
1164
1165+ The default value will be used by the shell if no value is present for this filter in the
1166+ unity::scopes::FilterState (no value has been set by the user).
1167+
1168 \return The default value
1169 */
1170 double default_value() const;
1171@@ -127,20 +116,6 @@
1172 double max() const;
1173
1174 /**
1175- \brief Get the label of this filter.
1176-
1177- \return The label
1178- */
1179- std::string label() const;
1180-
1181- /**
1182- \brief Get the value label template of this filter.
1183-
1184- \return The value label template.
1185- */
1186- std::string value_label_template() const;
1187-
1188- /**
1189 \brief Check if filter state object holds a value of this filter.
1190
1191 \return true if filter_state has a value of this filter.
1192@@ -150,12 +125,18 @@
1193 /**
1194 \brief Get value of this filter from filter state object.
1195
1196- \return value of this filter
1197- \throws unity::scopes::NotFoundException if value is not present in state object.
1198+ \return value of this filter or the default value if value is not present in the filter_state.
1199 */
1200 double value(FilterState const& filter_state) const;
1201
1202 /**
1203+ \brief Get value labeles for this slider filter.
1204+
1205+ \return the value labels.
1206+ */
1207+ ValueSliderLabels const& labels() const;
1208+
1209+ /**
1210 \brief Sets value of this filter instance in filter state object.
1211
1212 This is meant to be used to modify a FilterState received with a search request before sending it back to the client (UI shell).
1213@@ -178,8 +159,6 @@
1214 friend class internal::ValueSliderFilterImpl;
1215 };
1216
1217-} // namespace experimental
1218-
1219 } // namespace scopes
1220
1221 } // namespace unity
1222
1223=== added file 'include/unity/scopes/ValueSliderLabels.h'
1224--- include/unity/scopes/ValueSliderLabels.h 1970-01-01 00:00:00 +0000
1225+++ include/unity/scopes/ValueSliderLabels.h 2016-03-15 09:18:55 +0000
1226@@ -0,0 +1,122 @@
1227+/*
1228+ * Copyright (C) 2016 Canonical Ltd
1229+ *
1230+ * This program is free software: you can redistribute it and/or modify
1231+ * it under the terms of the GNU Lesser General Public License version 3 as
1232+ * published by the Free Software Foundation.
1233+ *
1234+ * This program is distributed in the hope that it will be useful,
1235+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1236+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1237+ * GNU Lesser General Public License for more details.
1238+ *
1239+ * You should have received a copy of the GNU Lesser General Public License
1240+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1241+ *
1242+ * Authored by: Pawel Stolowski <pawel.stolowski@canonical.com>
1243+ */
1244+
1245+#pragma once
1246+
1247+#include <string>
1248+#include <list>
1249+#include <memory>
1250+#include <unity/SymbolExport.h>
1251+#include <unity/scopes/Variant.h>
1252+
1253+namespace unity
1254+{
1255+
1256+namespace scopes
1257+{
1258+
1259+namespace internal
1260+{
1261+class ValueSliderFilterImpl;
1262+class ValueSliderLabelsImpl;
1263+}
1264+
1265+/**
1266+\brief A value and its corresponding label.
1267+*/
1268+typedef std::pair<double, std::string> ValueLabelPair;
1269+
1270+/**
1271+\brief A sequence of value-label pairs.
1272+*/
1273+typedef std::vector<ValueLabelPair> ValueLabelPairList;
1274+
1275+/**
1276+\brief Labels used by a ValueSliderFilter.
1277+
1278+The ValueSliderLabels class holds labels for a ValueSliderFilter. Labels for the minimum and maximum
1279+values must be provided. In addition, an arbitrary number of extra labels can be defined; these labels
1280+mark intermediate values between the minimum and maximum value.
1281+*/
1282+class UNITY_API ValueSliderLabels final
1283+{
1284+public:
1285+ /**@name Copy and assignment
1286+ Copy and assignment (move and non-move versions) have the usual value semantics.
1287+ */
1288+ //{@
1289+ ValueSliderLabels(ValueSliderLabels const& other);
1290+ ValueSliderLabels(ValueSliderLabels&&);
1291+ ValueSliderLabels& operator=(ValueSliderLabels const& other);
1292+ ValueSliderLabels& operator=(ValueSliderLabels&&);
1293+ ~ValueSliderLabels();
1294+ //@}
1295+
1296+ /**
1297+ \brief Create a ValueSliderLabels instance with labels for minimum and maximum values only.
1298+
1299+ \throws unity::InvalidArgumentException for invalid (empty or duplicated) labels.
1300+ */
1301+ ValueSliderLabels(std::string const& min_label, std::string const& max_label);
1302+
1303+ /**
1304+ \brief Create a ValueSliderLabels instance with labels for minimum and maximum, as well as extra labels.
1305+
1306+ Note that any extra labels act only as a guidance for the user (i.e. they do not limit the available choices).
1307+ The Unity shell is free to omit some or all of the labels depending on the available screen space.
1308+
1309+ \param min_label The label for minimum value of the associated ValueSliderFilter filter.
1310+ \param max_label The label for maximum value of the associated ValueSliderFilter filter.
1311+ \param extra_labels Additional labels for values between minimum and maximum values.
1312+
1313+ \throws unity::InvalidArgumentException on invalid labels (empty or duplicate labels, non-increasing values).
1314+ */
1315+ ValueSliderLabels(std::string const& min_label, std::string const& max_label, ValueLabelPairList const& extra_labels);
1316+
1317+ /**
1318+ \brief Get the label for the minimum value of the filter.
1319+ \return The label for the minimum value
1320+ */
1321+ std::string min_label() const;
1322+
1323+ /**
1324+ \brief Get the label for the maximum value of the filter.
1325+ \return The label for the maximum value
1326+ */
1327+ std::string max_label() const;
1328+
1329+ /**
1330+ \brief Get the labels for intermediate values of the filter.
1331+ */
1332+ ValueLabelPairList extra_labels() const;
1333+
1334+ /// @cond
1335+ VariantMap serialize() const;
1336+ /// @endcond
1337+
1338+private:
1339+ ValueSliderLabels(internal::ValueSliderLabelsImpl* pimpl);
1340+ ValueSliderLabels(VariantMap const& var);
1341+ std::unique_ptr<internal::ValueSliderLabelsImpl> p;
1342+ friend class internal::ValueSliderLabelsImpl;
1343+ friend class internal::ValueSliderFilterImpl;
1344+};
1345+
1346+} // namespace scopes
1347+
1348+} // namespace unity
1349
1350=== modified file 'include/unity/scopes/internal/ChildScopesRepository.h'
1351--- include/unity/scopes/internal/ChildScopesRepository.h 2015-04-01 10:15:25 +0000
1352+++ include/unity/scopes/internal/ChildScopesRepository.h 2016-03-15 09:18:55 +0000
1353@@ -43,7 +43,7 @@
1354 NONCOPYABLE(ChildScopesRepository);
1355
1356 ChildScopesRepository(std::string const& repo_file_path,
1357- boost::log::sources::severity_channel_logger_mt<>& logger);
1358+ unity::scopes::internal::Logger& logger);
1359
1360 ChildScopeList child_scopes(ChildScopeList const& child_scopes_defaulted);
1361 bool set_child_scopes(ChildScopeList const& child_scopes);
1362@@ -56,7 +56,7 @@
1363 ChildScopeEnabledMap json_to_list(std::string const& child_scopes_json);
1364
1365 std::string const repo_file_path_;
1366- boost::log::sources::severity_channel_logger_mt<>& logger_;
1367+ unity::scopes::internal::Logger& logger_;
1368
1369 std::mutex mutex_;
1370 ChildScopeEnabledMap cached_repo_;
1371
1372=== modified file 'include/unity/scopes/internal/DfltConfig.h.in'
1373--- include/unity/scopes/internal/DfltConfig.h.in 2015-12-09 05:43:13 +0000
1374+++ include/unity/scopes/internal/DfltConfig.h.in 2016-03-15 09:18:55 +0000
1375@@ -57,10 +57,6 @@
1376 static constexpr char const* DFLT_HOME_CACHE_SUBDIR = ".local/share/unity-scopes";
1377 static constexpr char const* DFLT_HOME_APP_SUBDIR = ".local/share";
1378 static constexpr char const* DFLT_HOME_CONFIG_SUBDIR = ".config/unity-scopes";
1379-static constexpr char const* DFLT_HOME_LOG_SUBDIR = "";
1380-
1381-static constexpr int DFLT_MAX_LOG_FILE_SIZE = 512 * 1024; // bytes, individual file size
1382-static constexpr int DFLT_MAX_LOG_DIR_SIZE = 2 * 1024 * 1024; // bytes, sum of file sizes
1383
1384 static constexpr bool DFLT_LOCATION_PERMITTED = true; // Whether a scope that wants location data, but does not
1385 // have a settings.ini file yet, actually gets the data.
1386
1387=== modified file 'include/unity/scopes/internal/FilterBaseImpl.h'
1388--- include/unity/scopes/internal/FilterBaseImpl.h 2015-11-12 14:20:36 +0000
1389+++ include/unity/scopes/internal/FilterBaseImpl.h 2016-03-15 09:18:55 +0000
1390@@ -20,7 +20,9 @@
1391
1392 #include <unity/scopes/Variant.h>
1393 #include <unity/scopes/FilterBase.h>
1394+#include <unity/scopes/FilterGroup.h>
1395 #include <string>
1396+#include <map>
1397
1398 namespace unity
1399 {
1400@@ -40,12 +42,16 @@
1401 virtual ~FilterBaseImpl();
1402 void set_display_hints(int hints);
1403 std::string id() const;
1404+ void set_title(std::string const& title);
1405+ std::string title() const;
1406 int display_hints() const;
1407+ void add_to_filter_group(FilterGroup::SCPtr const& group);
1408+ FilterGroup::SCPtr filter_group() const;
1409 VariantMap serialize() const;
1410 virtual std::string filter_type() const = 0;
1411 static FilterBase::SCPtr deserialize(VariantMap const& var);
1412 static VariantArray serialize_filters(Filters const& filters);
1413- static Filters deserialize_filters(VariantArray const& var);
1414+ static Filters deserialize_filters(VariantArray const& var, std::map<std::string, FilterGroup::SCPtr> const& groups);
1415 static void validate_filters(Filters const& filters);
1416 virtual void validate_display_hints() const = 0;
1417
1418@@ -56,7 +62,9 @@
1419
1420 private:
1421 std::string id_;
1422+ std::string title_;
1423 int display_hints_;
1424+ FilterGroup::SCPtr filter_group_;
1425 };
1426
1427 } // namespace internal
1428
1429=== added file 'include/unity/scopes/internal/FilterGroupImpl.h'
1430--- include/unity/scopes/internal/FilterGroupImpl.h 1970-01-01 00:00:00 +0000
1431+++ include/unity/scopes/internal/FilterGroupImpl.h 2016-03-15 09:18:55 +0000
1432@@ -0,0 +1,54 @@
1433+/*
1434+ * Copyright (C) 2016 Canonical Ltd
1435+ *
1436+ * This program is free software: you can redistribute it and/or modify
1437+ * it under the terms of the GNU Lesser General Public License version 3 as
1438+ * published by the Free Software Foundation.
1439+ *
1440+ * This program is distributed in the hope that it will be useful,
1441+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1442+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1443+ * GNU Lesser General Public License for more details.
1444+ *
1445+ * You should have received a copy of the GNU Lesser General Public License
1446+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1447+ *
1448+ * Authored by: Pawel Stolowski <pawel.stolowski@canonical.com>
1449+ */
1450+
1451+#pragma once
1452+
1453+#include <string>
1454+#include <map>
1455+#include <unity/scopes/Variant.h>
1456+#include <unity/scopes/FilterBase.h>
1457+
1458+namespace unity
1459+{
1460+
1461+namespace scopes
1462+{
1463+class FilterState;
1464+
1465+namespace internal
1466+{
1467+
1468+class FilterGroupImpl
1469+{
1470+public:
1471+ FilterGroupImpl(std::string const& id, std::string const& label);
1472+ std::string id() const;
1473+ std::string label() const;
1474+ static VariantArray serialize_filter_groups(Filters const& filters);
1475+ static std::map<std::string, FilterGroup::SCPtr> deserialize_filter_groups(VariantArray const& var);
1476+
1477+private:
1478+ std::string id_;
1479+ std::string label_;
1480+};
1481+
1482+} // namespace internal
1483+
1484+} // namespace scopes
1485+
1486+} // namespace unity
1487
1488=== modified file 'include/unity/scopes/internal/FilterOptionImpl.h'
1489--- include/unity/scopes/internal/FilterOptionImpl.h 2014-11-03 05:31:30 +0000
1490+++ include/unity/scopes/internal/FilterOptionImpl.h 2016-03-15 09:18:55 +0000
1491@@ -35,10 +35,13 @@
1492 FilterOptionImpl(std::string const& id, std::string const& label);
1493 std::string id() const;
1494 std::string label() const;
1495+ void set_default_value(bool default_value);
1496+ bool default_value() const;
1497
1498 private:
1499 std::string id_;
1500 std::string label_;
1501+ bool default_value_;
1502 };
1503
1504 } // namespace internal
1505
1506=== modified file 'include/unity/scopes/internal/Logger.h'
1507--- include/unity/scopes/internal/Logger.h 2014-12-10 04:00:08 +0000
1508+++ include/unity/scopes/internal/Logger.h 2016-03-15 09:18:55 +0000
1509@@ -20,18 +20,11 @@
1510
1511 #include <unity/util/DefinesPtrs.h>
1512 #include <unity/util/NonCopyable.h>
1513-#include <unity/util/ResourcePtr.h>
1514-
1515-#define BOOST_LOG_DYN_LINK
1516-
1517-#include <boost/log/sinks.hpp>
1518-#include <boost/log/sources/global_logger_storage.hpp>
1519-#include <boost/log/sources/record_ostream.hpp>
1520-#include <boost/log/sources/severity_channel_logger.hpp>
1521-#include <boost/log/utility/value_ref.hpp>
1522-
1523+
1524+#include <array>
1525 #include <atomic>
1526-#include <unordered_map>
1527+#include <iostream>
1528+#include <sstream>
1529
1530 namespace unity
1531 {
1532@@ -42,18 +35,58 @@
1533 namespace internal
1534 {
1535
1536-namespace
1537+enum class LoggerSeverity { Info, Warning, Error, Fatal, Trace };
1538+
1539+enum class LoggerChannel { DefaultChannel, IPC, LastChannelEnum_ };
1540+
1541+class Logger;
1542+
1543+class LogStream : public std::ostringstream
1544 {
1545-
1546-#pragma GCC diagnostic push
1547-#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
1548-
1549-BOOST_LOG_ATTRIBUTE_KEYWORD(severity, "Severity", int)
1550-BOOST_LOG_ATTRIBUTE_KEYWORD(channel, "Channel", std::string)
1551-
1552-#pragma GCC diagnostic pop
1553-
1554-}
1555+public:
1556+ NONCOPYABLE(LogStream);
1557+ UNITY_DEFINES_PTRS(LogStream);
1558+
1559+#if __GNUC__ == 4
1560+ // gcc 4.9 doesn't have a move constructor for ostringstream:
1561+ // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=54316
1562+ // We simulate the move with a copy and clear.
1563+ LogStream(LogStream&& other)
1564+ : id_(std::move(other.id_))
1565+ , outstream_(other.outstream_)
1566+ , severity_(other.severity_)
1567+ , channel_(other.channel_)
1568+ {
1569+ *this << other.str();
1570+ other.str("");
1571+ other.clear();
1572+ }
1573+#else
1574+ // We need an explicit move constructor because basic_ios does not have a move
1575+ // constructor. Instead, it has a protected move() method that ostringstream calls
1576+ // as part if its move constructor.
1577+ LogStream(LogStream&& other)
1578+ : std::ostringstream(std::move(other))
1579+ , id_(std::move(other.id_))
1580+ , outstream_(other.outstream_)
1581+ , severity_(other.severity_)
1582+ , channel_(other.channel_)
1583+ {
1584+ }
1585+#endif
1586+
1587+ LogStream& operator=(LogStream&&) = delete; // Move assignment is impossible due to reference member.
1588+
1589+ LogStream();
1590+ LogStream(std::ostream& outstream, std::string const& id, LoggerSeverity s, LoggerChannel c);
1591+ ~LogStream();
1592+
1593+private:
1594+ std::string const id_;
1595+ std::ostream& outstream_;
1596+ LoggerSeverity severity_;
1597+ LoggerChannel channel_;
1598+};
1599
1600 class Logger
1601 {
1602@@ -61,57 +94,42 @@
1603 NONCOPYABLE(Logger);
1604 UNITY_DEFINES_PTRS(Logger);
1605
1606- // Instantiate a logger that logs to std::clog.
1607- Logger(std::string const& id);
1608- ~Logger();
1609-
1610- enum Channel
1611+ // We need an explicit move constructor because atomics are not movable.
1612+ Logger(Logger&& other)
1613+ : id_(move(other.id_))
1614+ , outstream_(other.outstream_)
1615 {
1616- IPC,
1617- LastChannelEnum_
1618- };
1619-
1620- // Returns default logger (no channel)
1621- operator boost::log::sources::severity_channel_logger_mt<>&();
1622-
1623- // Returns logger for specified channel.
1624- boost::log::sources::severity_channel_logger_mt<>& operator()(Channel c);
1625-
1626- void set_log_file(std::string const& path, int rotation_size, int dir_size);
1627-
1628- enum Severity { Info, Warning, Error, Fatal, Trace };
1629- Severity set_severity_threshold(Severity s);
1630-
1631- bool set_channel(Channel c, bool enable);
1632+ severity_threshold_.exchange(other.severity_threshold_);
1633+ for (unsigned i = 0; i < other.enabled_.size(); ++i)
1634+ {
1635+ enabled_[i].exchange(other.enabled_[i]);
1636+ }
1637+ }
1638+
1639+ Logger& operator=(Logger&&) = delete; // Move assignment is impossible due to reference member.
1640+
1641+ // Instantiate a logger that logs to the given stream.
1642+ Logger(std::string const& id, std::ostream& outstream = std::clog);
1643+
1644+ // Returns default writer for severity Error on the default channel.
1645+ LogStream operator()();
1646+
1647+ // Returns writer for specified severity.
1648+ LogStream operator()(LoggerSeverity s);
1649+
1650+ // Returns writer for specified channel.
1651+ LogStream operator()(LoggerChannel c);
1652+
1653+ LoggerSeverity set_severity_threshold(LoggerSeverity s);
1654+
1655+ bool set_channel(LoggerChannel c, bool enable);
1656 bool set_channel(std::string channel_name, bool enable);
1657- void enable_channels(std::vector<std::string> const& names);
1658
1659 private:
1660- bool filter(boost::log::value_ref<int, tag::severity> const& level,
1661- boost::log::value_ref<std::string, tag::channel> const& channel);
1662-
1663- void formatter(boost::log::record_view const& rec,
1664- boost::log::formatting_ostream& strm);
1665-
1666- std::string scope_id_; // immutable
1667-
1668- boost::log::sources::severity_channel_logger_mt<> logger_; // Default logger, no channel, immutable
1669-
1670- std::atomic<Severity> severity_;
1671-
1672- typedef boost::log::sinks::asynchronous_sink<boost::log::sinks::text_ostream_backend> ClogSinkT;
1673- typedef boost::shared_ptr<ClogSinkT> ClogSinkPtr;
1674- ClogSinkPtr clog_sink_;
1675-
1676- typedef boost::log::sinks::asynchronous_sink<boost::log::sinks::text_file_backend> FileSinkT;
1677- typedef boost::shared_ptr<FileSinkT> FileSinkPtr;
1678- FileSinkPtr file_sink_;
1679-
1680- typedef std::pair<boost::log::sources::severity_channel_logger_mt<>, std::atomic_bool> ChannelData;
1681- typedef std::unordered_map<std::string, ChannelData> ChannelMap;
1682- ChannelMap channel_loggers_; // immutable
1683-
1684- std::mutex mutex_; // Protects clog_sink_ and file_sink_
1685+ std::string const id_;
1686+ std::ostream& outstream_;
1687+ std::atomic<LoggerSeverity> severity_threshold_;
1688+ std::array<std::atomic_bool, int(LoggerChannel::LastChannelEnum_)> enabled_;
1689 };
1690
1691 } // namespace internal
1692
1693=== modified file 'include/unity/scopes/internal/OptionSelectorFilterImpl.h'
1694--- include/unity/scopes/internal/OptionSelectorFilterImpl.h 2015-11-12 14:20:36 +0000
1695+++ include/unity/scopes/internal/OptionSelectorFilterImpl.h 2016-03-15 09:18:55 +0000
1696@@ -42,7 +42,7 @@
1697 OptionSelectorFilterImpl(VariantMap const& var);
1698 std::string label() const;
1699 bool multi_select() const;
1700- virtual FilterOption::SCPtr add_option(std::string const& id, std::string const& label);
1701+ virtual FilterOption::SCPtr add_option(std::string const& id, std::string const& label, bool default_value = false);
1702 std::list<FilterOption::SCPtr> options() const;
1703 int num_of_options() const;
1704 std::set<FilterOption::SCPtr> active_options(FilterState const& filter_state) const;
1705
1706=== modified file 'include/unity/scopes/internal/RangeInputFilterImpl.h'
1707--- include/unity/scopes/internal/RangeInputFilterImpl.h 2015-11-12 14:20:36 +0000
1708+++ include/unity/scopes/internal/RangeInputFilterImpl.h 2016-03-15 09:18:55 +0000
1709@@ -30,18 +30,25 @@
1710 namespace internal
1711 {
1712
1713-using namespace experimental;
1714-
1715 class RangeInputFilterImpl : public FilterBaseImpl
1716 {
1717 public:
1718- RangeInputFilterImpl(std::string const& id, std::string const& start_label, std::string const& end_label, std::string const& unit_label);
1719+ RangeInputFilterImpl(std::string const& id,
1720+ Variant const& default_start_value, Variant const& default_end_value,
1721+ std::string const& start_prefix_label, std::string const& start_postfix_label,
1722+ std::string const& central_label,
1723+ std::string const& end_prefix_label, std::string const& end_postfix_label);
1724+
1725 RangeInputFilterImpl(VariantMap const& var);
1726
1727- std::string start_label() const;
1728- std::string end_label() const;
1729- std::string unit_label() const;
1730+ std::string start_prefix_label() const;
1731+ std::string start_postfix_label() const;
1732+ std::string end_prefix_label() const;
1733+ std::string end_postfix_label() const;
1734+ std::string central_label() const;
1735
1736+ Variant default_start_value() const;
1737+ Variant default_end_value() const;
1738 bool has_start_value(FilterState const& filter_state) const;
1739 bool has_end_value(FilterState const& filter_state) const;
1740 double start_value(FilterState const& filter_state) const;
1741@@ -64,9 +71,13 @@
1742 double get_value(FilterState const& filter_state, unsigned int index) const;
1743 static void check_type(Variant const& val, std::string const& filter_id, std::string const& varname);
1744
1745- std::string start_label_;
1746- std::string end_label_;
1747- std::string unit_label_;
1748+ Variant default_start_value_;
1749+ Variant default_end_value_;
1750+ std::string start_prefix_label_;
1751+ std::string start_postfix_label_;
1752+ std::string end_prefix_label_;
1753+ std::string end_postfix_label_;
1754+ std::string central_label_;
1755 };
1756
1757 } // namespace internal
1758
1759=== modified file 'include/unity/scopes/internal/RatingFilterImpl.h'
1760--- include/unity/scopes/internal/RatingFilterImpl.h 2014-11-03 05:31:30 +0000
1761+++ include/unity/scopes/internal/RatingFilterImpl.h 2016-03-15 09:18:55 +0000
1762@@ -31,6 +31,8 @@
1763 {
1764
1765 using namespace experimental;
1766+// FIXME: reconsider using FilterOption and RadioButtonsFilterImpl as a base when moving this filter out from experimental namespace,
1767+// the default values of individual FilterOption don't make much sense with RatingFilter.
1768
1769 class RatingFilterImpl : public RadioButtonsFilterImpl
1770 {
1771@@ -38,7 +40,8 @@
1772 RatingFilterImpl(std::string const& id, std::string const& label);
1773 RatingFilterImpl(std::string const& id, std::string const& label, int top_rating);
1774 RatingFilterImpl(VariantMap const& var);
1775- FilterOption::SCPtr add_option(std::string const& id, std::string const& label) override;
1776+
1777+ FilterOption::SCPtr add_option(std::string const& id, std::string const& label, bool default_value = false) override;
1778 void set_on_icon(std::string const& on_icon);
1779 void set_off_icon(std::string const& off_icon);
1780 std::string on_icon() const;
1781
1782=== modified file 'include/unity/scopes/internal/RegistryObject.h'
1783--- include/unity/scopes/internal/RegistryObject.h 2015-12-08 01:02:15 +0000
1784+++ include/unity/scopes/internal/RegistryObject.h 2016-03-15 09:18:55 +0000
1785@@ -100,7 +100,7 @@
1786
1787 ScopeProcess(ScopeExecData exec_data,
1788 std::weak_ptr<MWPublisher> const& publisher,
1789- boost::log::sources::severity_channel_logger_mt<>& logger);
1790+ unity::scopes::internal::Logger& logger);
1791 ~ScopeProcess();
1792
1793 ProcessState state() const;
1794@@ -131,12 +131,12 @@
1795 core::posix::ChildProcess process_ = core::posix::ChildProcess::invalid();
1796 std::weak_ptr<MWPublisher> reg_publisher_; // weak_ptr, so processes don't hold publisher alive
1797 bool manually_started_;
1798- boost::log::sources::severity_channel_logger_mt<>& logger_;
1799+ unity::scopes::internal::Logger& logger_;
1800 };
1801
1802 private:
1803 std::unique_ptr<unity::scopes::internal::Logger> test_logger_;
1804- boost::log::sources::severity_channel_logger_mt<>& logger_;
1805+ unity::scopes::internal::Logger& logger_;
1806
1807 core::posix::ChildProcess::DeathObserver& death_observer_;
1808 core::ScopedConnection death_observer_connection_;
1809
1810=== modified file 'include/unity/scopes/internal/RuntimeConfig.h'
1811--- include/unity/scopes/internal/RuntimeConfig.h 2014-12-10 03:18:53 +0000
1812+++ include/unity/scopes/internal/RuntimeConfig.h 2016-03-15 09:18:55 +0000
1813@@ -47,15 +47,11 @@
1814 std::string cache_directory() const;
1815 std::string app_directory() const;
1816 std::string config_directory() const;
1817- std::string log_directory() const;
1818- int max_log_file_size() const;
1819- int max_log_dir_size() const;
1820 std::vector<std::string> trace_channels() const;
1821
1822 static std::string default_cache_directory();
1823 static std::string default_app_directory();
1824 static std::string default_config_directory();
1825- static std::string default_log_directory();
1826
1827 private:
1828 std::string registry_identity_;
1829@@ -69,9 +65,6 @@
1830 std::string cache_directory_;
1831 std::string app_directory_;
1832 std::string config_directory_;
1833- std::string log_directory_;
1834- int max_log_file_size_;
1835- int max_log_dir_size_;
1836 std::vector<std::string> trace_channels_;
1837 };
1838
1839
1840=== modified file 'include/unity/scopes/internal/RuntimeImpl.h'
1841--- include/unity/scopes/internal/RuntimeImpl.h 2015-03-02 03:59:01 +0000
1842+++ include/unity/scopes/internal/RuntimeImpl.h 2016-03-15 09:18:55 +0000
1843@@ -53,8 +53,7 @@
1844 Reaper::SPtr reply_reaper() const;
1845 ThreadPool::SPtr async_pool() const;
1846 ThreadSafeQueue<std::future<void>>::SPtr future_queue() const;
1847- boost::log::sources::severity_channel_logger_mt<>& logger() const;
1848- boost::log::sources::severity_channel_logger_mt<>& logger(Logger::Channel channel) const;
1849+ unity::scopes::internal::Logger& logger() const;
1850 void run_scope(ScopeBase* scope_base,
1851 std::string const& scope_ini_file,
1852 std::promise<void> ready_promise = std::promise<void>());
1853
1854=== modified file 'include/unity/scopes/internal/ValueSliderFilterImpl.h'
1855--- include/unity/scopes/internal/ValueSliderFilterImpl.h 2015-11-12 14:20:36 +0000
1856+++ include/unity/scopes/internal/ValueSliderFilterImpl.h 2016-03-15 09:18:55 +0000
1857@@ -20,6 +20,8 @@
1858
1859 #include <unity/scopes/internal/FilterBaseImpl.h>
1860 #include <unity/scopes/ValueSliderFilter.h>
1861+#include <unity/scopes/ValueSliderLabels.h>
1862+#include <unity/scopes/internal/ValueSliderLabelsImpl.h>
1863
1864 namespace unity
1865 {
1866@@ -32,24 +34,19 @@
1867 namespace internal
1868 {
1869
1870-using namespace experimental;
1871-
1872 class ValueSliderFilterImpl : public FilterBaseImpl
1873 {
1874 public:
1875- ValueSliderFilterImpl(std::string const& id, std::string const& label, std::string const& label_template, double min, double max);
1876+ ValueSliderFilterImpl(std::string const& id, double min, double max, double default_value, ValueSliderLabels const& labels);
1877 ValueSliderFilterImpl(VariantMap const& var);
1878- void set_slider_type(ValueSliderFilter::SliderType tp);
1879- ValueSliderFilter::SliderType slider_type() const;
1880 void set_default_value(double val);
1881- std::string label() const;
1882 double min() const;
1883 double max() const;
1884 double default_value() const;
1885- std::string value_label_template() const;
1886 bool has_value(FilterState const& filter_state) const;
1887 double value(FilterState const& filter_state) const;
1888 void update_state(FilterState& filter_state, double value) const;
1889+ ValueSliderLabels const& labels() const;
1890 static ValueSliderFilter::SPtr create(VariantMap const& var);
1891 static void update_state(FilterState& filter_state, std::string const& filter_id, double value);
1892 void validate_display_hints() const override;
1893@@ -61,12 +58,10 @@
1894 void check_range(double val) const;
1895
1896 private:
1897- std::string label_;
1898- std::string label_template_;
1899- ValueSliderFilter::SliderType slider_type_;
1900- double default_val_;
1901 double min_;
1902 double max_;
1903+ double default_val_;
1904+ std::unique_ptr<ValueSliderLabels> labels_;
1905 };
1906
1907 } // namespace internal
1908
1909=== added file 'include/unity/scopes/internal/ValueSliderLabelsImpl.h'
1910--- include/unity/scopes/internal/ValueSliderLabelsImpl.h 1970-01-01 00:00:00 +0000
1911+++ include/unity/scopes/internal/ValueSliderLabelsImpl.h 2016-03-15 09:18:55 +0000
1912@@ -0,0 +1,59 @@
1913+/*
1914+ * Copyright (C) 2015 Canonical Ltd
1915+ *
1916+ * This program is free software: you can redistribute it and/or modify
1917+ * it under the terms of the GNU Lesser General Public License version 3 as
1918+ * published by the Free Software Foundation.
1919+ *
1920+ * This program is distributed in the hope that it will be useful,
1921+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1922+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1923+ * GNU Lesser General Public License for more details.
1924+ *
1925+ * You should have received a copy of the GNU Lesser General Public License
1926+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1927+ *
1928+ * Authored by: Pawel Stolowski <pawel.stolowski@canonical.com>
1929+ */
1930+
1931+#pragma once
1932+
1933+#include <unity/scopes/ValueSliderLabels.h>
1934+#include <unity/scopes/Variant.h>
1935+
1936+namespace unity
1937+{
1938+
1939+namespace scopes
1940+{
1941+
1942+namespace internal
1943+{
1944+
1945+class ValueSliderLabelsImpl
1946+{
1947+public:
1948+ ValueSliderLabelsImpl(std::string const& min_label, std::string const& max_label);
1949+ ValueSliderLabelsImpl(std::string const& min_label, std::string const& max_label, std::vector<std::pair<double, std::string>> const& extra_labels);
1950+ ValueSliderLabelsImpl(VariantMap const& var);
1951+ ValueSliderLabelsImpl(ValueSliderLabelsImpl const&) = default;
1952+
1953+ std::string min_label() const;
1954+ std::string max_label() const;
1955+ std::vector<std::pair<double, std::string>> extra_labels() const;
1956+ VariantMap serialize() const;
1957+ void deserialize(VariantMap const& var);
1958+
1959+ void validate(double min, double max) const;
1960+
1961+private:
1962+ std::string min_label_;
1963+ std::string max_label_;
1964+ std::vector<std::pair<double, std::string>> extra_labels_;
1965+};
1966+
1967+}
1968+
1969+}
1970+
1971+}
1972
1973=== modified file 'include/unity/scopes/internal/smartscopes/SmartScopesClient.h'
1974--- include/unity/scopes/internal/smartscopes/SmartScopesClient.h 2015-12-08 01:02:15 +0000
1975+++ include/unity/scopes/internal/smartscopes/SmartScopesClient.h 2016-03-15 09:18:55 +0000
1976@@ -20,6 +20,7 @@
1977
1978 #include <unity/scopes/FilterBase.h>
1979 #include <unity/scopes/FilterState.h>
1980+#include <unity/scopes/FilterGroup.h>
1981 #include <unity/scopes/internal/JsonNodeInterface.h>
1982 #include <unity/scopes/internal/Logger.h>
1983 #include <unity/scopes/internal/smartscopes/HttpClientInterface.h>
1984@@ -27,12 +28,13 @@
1985
1986 #include <unity/util/NonCopyable.h>
1987
1988-#include <string>
1989-#include <vector>
1990 #include <map>
1991 #include <memory>
1992 #include <mutex>
1993+#include <set>
1994+#include <string>
1995 #include <tuple>
1996+#include <vector>
1997
1998 namespace unity
1999 {
2000@@ -152,6 +154,8 @@
2001 std::function<void(std::shared_ptr<DepartmentInfo> const&)> departments_handler;
2002 std::function<void(Filters const&)> filters_handler;
2003 std::function<void(FilterState const&)> filter_state_handler;
2004+
2005+ std::map<std::string, FilterGroup::SCPtr> filter_groups;
2006 };
2007
2008 struct PreviewReplyHandler
2009@@ -179,7 +183,7 @@
2010
2011 bool get_remote_scopes(std::vector<RemoteScope>& scopes, std::string const& locale = "", bool caching_enabled = true);
2012
2013- SearchHandle::UPtr search(SearchReplyHandler const& handler,
2014+ SearchHandle::UPtr search(SearchReplyHandler& handler,
2015 std::string const& base_url,
2016 std::string const& query,
2017 std::string const& department_id,
2018@@ -204,7 +208,7 @@
2019 std::string const& country = "",
2020 std::string const& user_agent_hdr = "");
2021
2022- boost::log::sources::severity_channel_logger_mt<>& logger() const;
2023+ unity::scopes::internal::Logger& logger() const;
2024
2025 private:
2026 friend class SearchHandle;
2027@@ -213,11 +217,12 @@
2028 void wait_for_search(unsigned int search_id);
2029 void wait_for_preview(unsigned int preview_id);
2030 std::shared_ptr<DepartmentInfo> parse_departments(JsonNodeInterface::SPtr node);
2031- Filters parse_filters(JsonNodeInterface::SPtr node);
2032+ std::map<std::string, FilterGroup::SCPtr> parse_filter_groups(JsonNodeInterface::SPtr node);
2033+ Filters parse_filters(JsonNodeInterface::SPtr node, std::map<std::string, FilterGroup::SCPtr> const& filter_groups);
2034 FilterState parse_filter_state(JsonNodeInterface::SPtr node);
2035
2036 std::string handle_chunk(const std::string& chunk, std::function<void(const std::string&)> line_handler);
2037- void handle_line(std::string const& json, SearchReplyHandler const& handler);
2038+ void handle_line(std::string const& json, SearchReplyHandler& handler);
2039 void handle_line(std::string const& json, PreviewReplyHandler const& handler);
2040
2041 std::vector<std::string> extract_json_stream(std::string const& json_stream);
2042@@ -232,7 +237,7 @@
2043 HttpClientInterface::SPtr http_client_;
2044 JsonNodeInterface::SPtr json_node_;
2045 std::unique_ptr<unity::scopes::internal::Logger> test_logger_;
2046- boost::log::sources::severity_channel_logger_mt<>& logger_;
2047+ unity::scopes::internal::Logger& logger_;
2048 std::string url_;
2049
2050 std::map<unsigned int, HttpResponseHandle::SPtr> query_results_;
2051
2052=== modified file 'include/unity/scopes/internal/zmq_middleware/ObjectAdapter.h'
2053--- include/unity/scopes/internal/zmq_middleware/ObjectAdapter.h 2015-12-08 01:02:15 +0000
2054+++ include/unity/scopes/internal/zmq_middleware/ObjectAdapter.h 2016-03-15 09:18:55 +0000
2055@@ -109,8 +109,7 @@
2056
2057 void store_exception(scopes::MiddlewareException& ex);
2058
2059- boost::log::sources::severity_channel_logger_mt<>& logger() const;
2060- boost::log::sources::severity_channel_logger_mt<>& ipc_logger() const;
2061+ unity::scopes::internal::Logger& logger() const;
2062
2063 void trace_dispatch(Current const& c);
2064 void trace_response();
2065
2066=== modified file 'include/unity/scopes/internal/zmq_middleware/ZmqMiddleware.h'
2067--- include/unity/scopes/internal/zmq_middleware/ZmqMiddleware.h 2015-12-08 01:02:15 +0000
2068+++ include/unity/scopes/internal/zmq_middleware/ZmqMiddleware.h 2016-03-15 09:18:55 +0000
2069@@ -135,7 +135,7 @@
2070 mutable std::mutex state_mutex_; // Protects state_
2071 std::atomic_bool shutdown_flag_;
2072 std::unique_ptr<unity::scopes::internal::Logger> test_logger_;
2073- boost::log::sources::severity_channel_logger_mt<>& logger_;
2074+ unity::scopes::internal::Logger& logger_;
2075
2076 int64_t twoway_timeout_; // Default timeout for twoway invocations
2077 int64_t locate_timeout_; // Timeout for registry locate()
2078
2079=== modified file 'scoperegistry/DirWatcher.cpp'
2080--- scoperegistry/DirWatcher.cpp 2015-01-07 02:24:43 +0000
2081+++ scoperegistry/DirWatcher.cpp 2016-03-15 09:18:55 +0000
2082@@ -32,7 +32,7 @@
2083 namespace scoperegistry
2084 {
2085
2086-DirWatcher::DirWatcher(boost::log::sources::severity_channel_logger_mt<>& logger)
2087+DirWatcher::DirWatcher(Logger& logger)
2088 : fd_(inotify_init())
2089 , thread_state_(Running)
2090 , thread_exception_(nullptr)
2091@@ -137,11 +137,11 @@
2092 }
2093 catch (std::exception const& e)
2094 {
2095- BOOST_LOG(logger_) << "~DirWatcher(): " << e.what();
2096+ logger_() << "~DirWatcher(): " << e.what();
2097 }
2098 catch (...)
2099 {
2100- BOOST_LOG(logger_) << "~DirWatcher(): watch_thread was aborted due to an unknown exception";
2101+ logger_() << "~DirWatcher(): watch_thread was aborted due to an unknown exception";
2102 }
2103 }
2104 else
2105@@ -283,14 +283,14 @@
2106 }
2107 catch (std::exception const& e)
2108 {
2109- BOOST_LOG(logger_) << "DirWatcher::watch_thread(): " << e.what();
2110+ logger_() << "DirWatcher::watch_thread(): " << e.what();
2111 std::lock_guard<std::mutex> lock(mutex_);
2112 thread_state_ = Failed;
2113 thread_exception_ = std::current_exception();
2114 }
2115 catch (...)
2116 {
2117- BOOST_LOG(logger_) << "DirWatcher::watch_thread(): Thread aborted: unknown exception";
2118+ logger_() << "DirWatcher::watch_thread(): Thread aborted: unknown exception";
2119 std::lock_guard<std::mutex> lock(mutex_);
2120 thread_state_ = Failed;
2121 thread_exception_ = std::current_exception();
2122
2123=== modified file 'scoperegistry/DirWatcher.h'
2124--- scoperegistry/DirWatcher.h 2014-11-24 05:06:00 +0000
2125+++ scoperegistry/DirWatcher.h 2016-03-15 09:18:55 +0000
2126@@ -48,7 +48,7 @@
2127 Directory
2128 };
2129
2130- DirWatcher(boost::log::sources::severity_channel_logger_mt<>& logger);
2131+ DirWatcher(unity::scopes::internal::Logger& logger);
2132 virtual ~DirWatcher();
2133
2134 void add_watch(std::string const& path);
2135@@ -73,7 +73,7 @@
2136 std::mutex mutex_;
2137 ThreadState thread_state_;
2138 std::exception_ptr thread_exception_;
2139- boost::log::sources::severity_channel_logger_mt<>& logger_;
2140+ unity::scopes::internal::Logger& logger_;
2141
2142 void watch_thread();
2143 virtual void watch_event(EventType, FileType, std::string const&) = 0;
2144
2145=== modified file 'scoperegistry/ScopesWatcher.cpp'
2146--- scoperegistry/ScopesWatcher.cpp 2015-01-20 06:18:36 +0000
2147+++ scoperegistry/ScopesWatcher.cpp 2016-03-15 09:18:55 +0000
2148@@ -35,7 +35,7 @@
2149
2150 ScopesWatcher::ScopesWatcher(RegistryObject::SPtr registry,
2151 std::function<void(std::pair<std::string, std::string> const&)> ini_added_callback,
2152- boost::log::sources::severity_channel_logger_mt<>& logger)
2153+ Logger& logger)
2154 : DirWatcher(logger)
2155 , registry_(registry)
2156 , ini_added_callback_(ini_added_callback)
2157@@ -60,7 +60,7 @@
2158 catch (unity::LogicException const&) {} // Ignore already exists exception
2159 catch (unity::SyscallException const& e)
2160 {
2161- BOOST_LOG(logger_) << "ScopesWatcher::add_install_dir(): parent dir watch: " << e.what();
2162+ logger_() << "ScopesWatcher::add_install_dir(): parent dir watch: " << e.what();
2163 }
2164
2165 // Create a new entry for this install dir into idir_to_sdirs_map_
2166@@ -101,11 +101,11 @@
2167 }
2168 catch (unity::ResourceException const& e)
2169 {
2170- BOOST_LOG(logger_) << "ScopesWatcher::add_install_dir(): install dir watch: " << e.what();
2171+ logger_() << "ScopesWatcher::add_install_dir(): install dir watch: " << e.what();
2172 }
2173 catch (unity::SyscallException const& e)
2174 {
2175- BOOST_LOG(logger_) << "ScopesWatcher::add_install_dir(): install dir watch: " << e.what();
2176+ logger_() << "ScopesWatcher::add_install_dir(): install dir watch: " << e.what();
2177 }
2178 }
2179
2180@@ -196,13 +196,13 @@
2181
2182 // New config found, execute callback
2183 ini_added_callback_(config);
2184- BOOST_LOG_SEV(logger_, Logger::Info)
2185- << "ScopesWatcher: scope: \"" << config.first << "\" installed to: \"" << dir << "\"";
2186+ logger_(LoggerSeverity::Info) << "ScopesWatcher: scope: \"" << config.first
2187+ << "\" installed to: \"" << dir << "\"";
2188 }
2189 }
2190 catch (std::exception const& e)
2191 {
2192- BOOST_LOG(logger_) << "scoperegistry: add_scope_dir(): " << e.what();
2193+ logger_() << "scoperegistry: add_scope_dir(): " << e.what();
2194 }
2195 }
2196
2197@@ -227,8 +227,8 @@
2198 filesystem::path p(ini_path);
2199 std::string scope_id = p.stem().native();
2200 registry_->remove_local_scope(scope_id);
2201- BOOST_LOG_SEV(logger_, Logger::Info)
2202- << "ScopesWatcher: scope: \"" << scope_id << "\" uninstalled from: \"" << dir << "\"";
2203+ logger_(LoggerSeverity::Info) << "ScopesWatcher: scope: \"" << scope_id
2204+ << "\" uninstalled from: \"" << dir << "\"";
2205 }
2206
2207 // Remove the watch for this directory
2208@@ -273,8 +273,8 @@
2209 {
2210 sdir_to_ini_map_[parent_path] = path;
2211 ini_added_callback_(std::make_pair(scope_id, path));
2212- BOOST_LOG_SEV(logger_, Logger::Info)
2213- << "scopeswatcher: scope: \"" << scope_id << "\" .ini installed: \"" << path << "\"";
2214+ logger_(LoggerSeverity::Info) << "scopeswatcher: scope: \"" << scope_id
2215+ << "\" .ini installed: \"" << path << "\"";
2216 }
2217 }
2218 // a .ini has been removed
2219@@ -282,9 +282,8 @@
2220 {
2221 sdir_to_ini_map_.erase(parent_path);
2222 registry_->remove_local_scope(scope_id);
2223- BOOST_LOG_SEV(logger_, Logger::Info)
2224- << "scopeswatcher: scope: \"" << scope_id << "\" .ini uninstalled: \""
2225- << path << "\"";
2226+ logger_(LoggerSeverity::Info) << "scopeswatcher: scope: \"" << scope_id
2227+ << "\" .ini uninstalled: \"" << path << "\"";
2228 }
2229 }
2230 else
2231@@ -317,7 +316,7 @@
2232 {
2233 bool is_inside_install_dir;
2234 {
2235- std::lock_guard<std::mutex> lock(mutex);
2236+ std::lock_guard<std::mutex> lock(mutex_);
2237 is_inside_install_dir = idir_to_sdirs_map_.find(parent_dir(path)) != idir_to_sdirs_map_.end();
2238 }
2239
2240
2241=== modified file 'scoperegistry/ScopesWatcher.h'
2242--- scoperegistry/ScopesWatcher.h 2014-11-28 06:41:23 +0000
2243+++ scoperegistry/ScopesWatcher.h 2016-03-15 09:18:55 +0000
2244@@ -34,7 +34,7 @@
2245 public:
2246 ScopesWatcher(unity::scopes::internal::RegistryObject::SPtr registry,
2247 std::function<void(std::pair<std::string, std::string> const&)> ini_added_callback,
2248- boost::log::sources::severity_channel_logger_mt<>& logger);
2249+ unity::scopes::internal::Logger& logger);
2250
2251 ~ScopesWatcher();
2252
2253@@ -43,7 +43,7 @@
2254 private:
2255 unity::scopes::internal::RegistryObject::SPtr const registry_;
2256 std::function<void(std::pair<std::string, std::string> const&)> const ini_added_callback_;
2257- boost::log::sources::severity_channel_logger_mt<>& logger_;
2258+ unity::scopes::internal::Logger& logger_;
2259 std::map<std::string, std::string> sdir_to_ini_map_;
2260 std::map<std::string, std::set<std::string>> idir_to_sdirs_map_;
2261 std::mutex mutex_;
2262
2263=== modified file 'src/scopes/CMakeLists.txt'
2264--- src/scopes/CMakeLists.txt 2015-04-09 15:59:17 +0000
2265+++ src/scopes/CMakeLists.txt 2016-03-15 09:18:55 +0000
2266@@ -22,6 +22,7 @@
2267 ${CMAKE_CURRENT_SOURCE_DIR}/Department.cpp
2268 ${CMAKE_CURRENT_SOURCE_DIR}/DateTimePickerFilter.cpp
2269 ${CMAKE_CURRENT_SOURCE_DIR}/FilterBase.cpp
2270+ ${CMAKE_CURRENT_SOURCE_DIR}/FilterGroup.cpp
2271 ${CMAKE_CURRENT_SOURCE_DIR}/FilterOption.cpp
2272 ${CMAKE_CURRENT_SOURCE_DIR}/FilterState.cpp
2273 ${CMAKE_CURRENT_SOURCE_DIR}/Link.cpp
2274@@ -55,6 +56,7 @@
2275 ${CMAKE_CURRENT_SOURCE_DIR}/SearchReply.cpp
2276 ${CMAKE_CURRENT_SOURCE_DIR}/SwitchFilter.cpp
2277 ${CMAKE_CURRENT_SOURCE_DIR}/ValueSliderFilter.cpp
2278+ ${CMAKE_CURRENT_SOURCE_DIR}/ValueSliderLabels.cpp
2279 ${CMAKE_CURRENT_SOURCE_DIR}/VariantBuilder.cpp
2280 ${CMAKE_CURRENT_SOURCE_DIR}/Variant.cpp
2281 ${CMAKE_CURRENT_SOURCE_DIR}/Version.cpp
2282
2283=== modified file 'src/scopes/CategoryRenderer.cpp'
2284--- src/scopes/CategoryRenderer.cpp 2015-01-07 22:36:31 +0000
2285+++ src/scopes/CategoryRenderer.cpp 2016-03-15 09:18:55 +0000
2286@@ -49,8 +49,12 @@
2287
2288 As specified by the \c "category-layout" key of the \c "template" dictionary, Unity will render results associated with this category in a grid layout. The \c "components" dictionary specifies which result fields are used by Unity. In case of this definition, each tile of the grid will map the "title" field from the result (set also by the call to unity::scopes::Result::set_title()) as title for the grid tile, and "art" field from the result (see unity::scopes::Result::set_art()) as the icon for the grid tile.
2289
2290-To sum up, the \c "template" dictionary contains information to determine the correct renderer and its parameters, and the \c "components" dictionary contains mapping specifying which fields of the results are used by the renderer, where keys of the dictionary are understood by Unity and values specify either field name of the results directly (<tt>{"title": "album_name"}</tt> would mean that Unity will use <tt>result["album_name"]</tt> as a title for the grid tile), or the value can specify extra hints for the renderer as well as the result field name and a fallback image
2291-(<tt>{"art": {"field": "icon", "aspect-ratio": 1.3, "fallback": "file:///path_to_fallback_image}}</tt>).
2292+To sum up, the \c "template" dictionary contains information to determine the correct renderer and its parameters, and the \c "components" dictionary contains a mapping that specifies which fields of the results are used by the renderer.
2293+The keys of the dictionary are understood by Unity and the values specify a field name of the results. For example, <tt>{"title": "album_name"}</tt> means that Unity will use <tt>result["album_name"]</tt> as a title for the grid tile.r
2294+
2295+A value also can specify extra hints for the renderer, such as the result field name and a fallback image. For example,
2296+<tt>{"art": {"field": "icon", "aspect-ratio": 1.3, "fallback": "file:///path_to_fallback_image}}</tt>.
2297+The fallback image is shown by Unity if no image URL is provided by the result, but the card requires an image. The fallback image is also shown if the result provides an empty URL for an image, the image does not load due to an error, or if loading results in an empty image. If a result does not specify a fallback image and the actual image is empty or cannot be loaded, Unity substitutes a generic fallback image.
2298
2299 \section jsonschema1 JSON structure (v1)
2300
2301@@ -65,6 +69,7 @@
2302 \arg \c collapsed-rows Number of result rows displayed while the category is collapsed; possible values: any non-negative integer, where 0 fully expands the category (only affects grid and vertical journal)
2303 \arg \c card-background Background color for the cards; string; URI in the format \verbatim color:///#rrggbb \endverbatim or \verbatim color:///color_name
2304 \endverbatim or \verbatim gradient:///#rrggbb/#rrggbb \endverbatim or an image URI (will be stretched)
2305+\arg \c quick-preview-type The type of media content represented by result cards, for use with inline playback; the only currently supported type is "audio".
2306
2307 \subsection components1 components keys
2308
2309@@ -79,6 +84,8 @@
2310 \arg \c background Card background URI, can override the default specified in the card-background field of the template section (same format as for card-background)
2311 \arg \c attributes Array of dictionaries specifying text and an optional icon (keys: "value", "icon")
2312 \arg \c overlay-color Color of overlay for templates with overlay
2313+\arg \c quick-preview-data A dictionary with the following keys: \c "uri" (an uri of audio stream or file), \c "duration" (duration in seconds), \c "playlist"
2314+(an array of uris of additional songs to be played in sequence when the main song finishes).
2315
2316 \section example Example
2317
2318
2319=== modified file 'src/scopes/FilterBase.cpp'
2320--- src/scopes/FilterBase.cpp 2015-11-12 14:20:36 +0000
2321+++ src/scopes/FilterBase.cpp 2016-03-15 09:18:55 +0000
2322@@ -54,6 +54,16 @@
2323 return p->id();
2324 }
2325
2326+void FilterBase::set_title(std::string const& title)
2327+{
2328+ p->set_title(title);
2329+}
2330+
2331+std::string FilterBase::title() const
2332+{
2333+ return p->title();
2334+}
2335+
2336 int FilterBase::display_hints() const
2337 {
2338 return p->display_hints();
2339@@ -64,6 +74,11 @@
2340 return p->filter_type();
2341 }
2342
2343+FilterGroup::SCPtr FilterBase::filter_group() const
2344+{
2345+ return p->filter_group();
2346+}
2347+
2348 } // namespace scopes
2349
2350 } // namespace unity
2351
2352=== added file 'src/scopes/FilterGroup.cpp'
2353--- src/scopes/FilterGroup.cpp 1970-01-01 00:00:00 +0000
2354+++ src/scopes/FilterGroup.cpp 2016-03-15 09:18:55 +0000
2355@@ -0,0 +1,56 @@
2356+/*
2357+ * Copyright (C) 2016 Canonical Ltd
2358+ *
2359+ * This program is free software: you can redistribute it and/or modify
2360+ * it under the terms of the GNU Lesser General Public License version 3 as
2361+ * published by the Free Software Foundation.
2362+ *
2363+ * This program is distributed in the hope that it will be useful,
2364+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2365+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2366+ * GNU Lesser General Public License for more details.
2367+ *
2368+ * You should have received a copy of the GNU Lesser General Public License
2369+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2370+ *
2371+ * Authored by: Pawel Stolowski <pawel.stolowski@canonical.com>
2372+ */
2373+
2374+#include <unity/scopes/FilterGroup.h>
2375+#include <unity/scopes/internal/FilterGroupImpl.h>
2376+
2377+namespace unity
2378+{
2379+
2380+namespace scopes
2381+{
2382+
2383+/// @cond
2384+FilterGroup::FilterGroup(internal::FilterGroupImpl *pimpl)
2385+ : p(pimpl)
2386+{
2387+}
2388+
2389+FilterGroup::FilterGroup() = default;
2390+FilterGroup::~FilterGroup() = default;
2391+
2392+/// @endcond
2393+
2394+FilterGroup::SCPtr FilterGroup::create(std::string const& id, std::string const& label)
2395+{
2396+ return std::shared_ptr<FilterGroup>(new FilterGroup(new internal::FilterGroupImpl(id, label)));
2397+}
2398+
2399+std::string FilterGroup::label() const
2400+{
2401+ return p->label();
2402+}
2403+
2404+std::string FilterGroup::id() const
2405+{
2406+ return p->id();
2407+}
2408+
2409+} // namespace scopes
2410+
2411+} // namespace unity
2412
2413=== modified file 'src/scopes/FilterOption.cpp'
2414--- src/scopes/FilterOption.cpp 2014-02-25 14:59:28 +0000
2415+++ src/scopes/FilterOption.cpp 2016-03-15 09:18:55 +0000
2416@@ -44,6 +44,11 @@
2417 return p->label();
2418 }
2419
2420+bool FilterOption::default_value() const
2421+{
2422+ return p->default_value();
2423+}
2424+
2425 } // namespace scopes
2426
2427 } // namespace unity
2428
2429=== modified file 'src/scopes/OptionSelectorFilter.cpp'
2430--- src/scopes/OptionSelectorFilter.cpp 2014-05-19 09:54:37 +0000
2431+++ src/scopes/OptionSelectorFilter.cpp 2016-03-15 09:18:55 +0000
2432@@ -35,6 +35,13 @@
2433 return std::unique_ptr<OptionSelectorFilter>(new OptionSelectorFilter(new internal::OptionSelectorFilterImpl(id, label, multi_select)));
2434 }
2435
2436+OptionSelectorFilter::UPtr OptionSelectorFilter::create(std::string const& id, std::string const& label, FilterGroup::SCPtr const& group, bool multi_select)
2437+{
2438+ auto filter = std::unique_ptr<OptionSelectorFilter>(new OptionSelectorFilter(new internal::OptionSelectorFilterImpl(id, label, multi_select)));
2439+ filter->p->add_to_filter_group(group);
2440+ return filter;
2441+}
2442+
2443 std::string OptionSelectorFilter::label() const
2444 {
2445 return fwd()->label();
2446@@ -47,7 +54,12 @@
2447
2448 FilterOption::SCPtr OptionSelectorFilter::add_option(std::string const& id, std::string const& label)
2449 {
2450- return fwd()->add_option(id, label);
2451+ return fwd()->add_option(id, label, false);
2452+}
2453+
2454+FilterOption::SCPtr OptionSelectorFilter::add_option(std::string const& id, std::string const& label, bool value)
2455+{
2456+ return fwd()->add_option(id, label, value);
2457 }
2458
2459 std::list<FilterOption::SCPtr> OptionSelectorFilter::options() const
2460
2461=== modified file 'src/scopes/PreviewWidget.cpp'
2462--- src/scopes/PreviewWidget.cpp 2015-12-10 16:26:30 +0000
2463+++ src/scopes/PreviewWidget.cpp 2016-03-15 09:18:55 +0000
2464@@ -158,7 +158,7 @@
2465
2466 \arg \c source A URI pointing to the image
2467 \arg \c zoomable A boolean specifying whether the image is zoomable (default: \c false)
2468-\arg \c fallback A fallback image to be used if the image URI cannot be retrieved (default: none)
2469+\arg \c fallback A fallback image to be used if the image URI is empty or cannot be retrieved (default: none)
2470 \arg \c share-data An optional dictionary for making this image shareable with Content Hub. See \link contentsharing content sharing\endlink below.
2471
2472 \code{.cpp}
2473@@ -178,7 +178,7 @@
2474 List of attributes:
2475
2476 \arg \c sources An array of image URIs
2477-\arg \c fallback A fallback image to be used if an image URI cannot be resolved (default: none)
2478+\arg \c fallback A fallback image to be used if an image URI is empty or cannot be retrieved (default: none)
2479
2480 \code{.cpp}
2481 {
2482@@ -203,7 +203,7 @@
2483 \arg \c title A string specifying the title
2484 \arg \c subtitle A string specifying the subtitle
2485 \arg \c mascot A URI specifying the mascot
2486-\arg \c fallback A fallback image to be used if the mascot URI cannot be retrieved (default: none)
2487+\arg \c fallback A fallback image to be used if the mascot URI is empty or cannot be retrieved (default: none)
2488 \arg \c emblem A URI specifying the emblem
2489
2490 \code{.cpp}
2491
2492=== modified file 'src/scopes/RangeInputFilter.cpp'
2493--- src/scopes/RangeInputFilter.cpp 2014-06-17 10:30:03 +0000
2494+++ src/scopes/RangeInputFilter.cpp 2016-03-15 09:18:55 +0000
2495@@ -26,32 +26,105 @@
2496 namespace scopes
2497 {
2498
2499-namespace experimental
2500-{
2501-
2502-RangeInputFilter::SPtr RangeInputFilter::create(std::string const& id, std::string const& start_label, std::string const& end_label, std::string const& unit_label)
2503-{
2504- return std::shared_ptr<RangeInputFilter>(new RangeInputFilter(new internal::RangeInputFilterImpl(id, start_label, end_label, unit_label)));
2505-}
2506+RangeInputFilter::SPtr RangeInputFilter::create(std::string const& id,
2507+ std::string const& start_prefix_label, std::string const& start_postfix_label,
2508+ std::string const& central_label,
2509+ std::string const& end_prefix_label, std::string const& end_postfix_label)
2510+{
2511+ return std::shared_ptr<RangeInputFilter>(new RangeInputFilter(new internal::RangeInputFilterImpl(id,
2512+ Variant::null(), Variant::null(),
2513+ start_prefix_label, start_postfix_label,
2514+ central_label,
2515+ end_prefix_label, end_postfix_label)));
2516+}
2517+
2518+RangeInputFilter::SPtr RangeInputFilter::create(std::string const& id,
2519+ Variant const& default_start_value,
2520+ Variant const& default_end_value,
2521+ std::string const& start_prefix_label, std::string const& start_postfix_label,
2522+ std::string const& central_label,
2523+ std::string const& end_prefix_label, std::string const& end_postfix_label)
2524+{
2525+ return std::shared_ptr<RangeInputFilter>(new RangeInputFilter(new internal::RangeInputFilterImpl(id,
2526+ default_start_value, default_end_value,
2527+ start_prefix_label, start_postfix_label,
2528+ central_label,
2529+ end_prefix_label, end_postfix_label)));
2530+}
2531+
2532+RangeInputFilter::SPtr RangeInputFilter::create(std::string const& id,
2533+ std::string const& start_prefix_label, std::string const& start_postfix_label,
2534+ std::string const& central_label,
2535+ std::string const& end_prefix_label, std::string const& end_postfix_label,
2536+ FilterGroup::SCPtr const& group
2537+ )
2538+{
2539+ auto filter = std::shared_ptr<RangeInputFilter>(new RangeInputFilter(new internal::RangeInputFilterImpl(id,
2540+ Variant::null(), Variant::null(),
2541+ start_prefix_label, start_postfix_label,
2542+ central_label,
2543+ end_prefix_label, end_postfix_label)));
2544+ filter->p->add_to_filter_group(group);
2545+ return filter;
2546+}
2547+
2548+RangeInputFilter::SPtr RangeInputFilter::create(std::string const& id,
2549+ Variant const& default_start_value,
2550+ Variant const& default_end_value,
2551+ std::string const& start_prefix_label, std::string const& start_postfix_label,
2552+ std::string const& central_label,
2553+ std::string const& end_prefix_label, std::string const& end_postfix_label,
2554+ FilterGroup::SCPtr const& group
2555+ )
2556+{
2557+ auto filter = std::shared_ptr<RangeInputFilter>(new RangeInputFilter(new internal::RangeInputFilterImpl(id,
2558+ default_start_value, default_end_value,
2559+ start_prefix_label, start_postfix_label,
2560+ central_label,
2561+ end_prefix_label, end_postfix_label)));
2562+ filter->p->add_to_filter_group(group);
2563+ return filter;
2564+}
2565+
2566
2567 RangeInputFilter::RangeInputFilter(internal::RangeInputFilterImpl* impl)
2568 : FilterBase(impl)
2569 {
2570 }
2571
2572-std::string RangeInputFilter::start_label() const
2573-{
2574- return fwd()->start_label();
2575-}
2576-
2577-std::string RangeInputFilter::end_label() const
2578-{
2579- return fwd()->end_label();
2580-}
2581-
2582-std::string RangeInputFilter::unit_label() const
2583-{
2584- return fwd()->unit_label();
2585+std::string RangeInputFilter::start_prefix_label() const
2586+{
2587+ return fwd()->start_prefix_label();
2588+}
2589+
2590+std::string RangeInputFilter::start_postfix_label() const
2591+{
2592+ return fwd()->start_postfix_label();
2593+}
2594+
2595+std::string RangeInputFilter::end_prefix_label() const
2596+{
2597+ return fwd()->end_prefix_label();
2598+}
2599+
2600+std::string RangeInputFilter::end_postfix_label() const
2601+{
2602+ return fwd()->end_postfix_label();
2603+}
2604+
2605+std::string RangeInputFilter::central_label() const
2606+{
2607+ return fwd()->central_label();
2608+}
2609+
2610+Variant RangeInputFilter::default_start_value() const
2611+{
2612+ return fwd()->default_start_value();
2613+}
2614+
2615+Variant RangeInputFilter::default_end_value() const
2616+{
2617+ return fwd()->default_end_value();
2618 }
2619
2620 bool RangeInputFilter::has_start_value(FilterState const& filter_state) const
2621@@ -89,8 +162,6 @@
2622 return dynamic_cast<internal::RangeInputFilterImpl*>(p.get());
2623 }
2624
2625-} // namespace experimental
2626-
2627 } // namespace scopes
2628
2629 } // namespace unity
2630
2631=== modified file 'src/scopes/ValueSliderFilter.cpp'
2632--- src/scopes/ValueSliderFilter.cpp 2014-06-17 10:30:03 +0000
2633+++ src/scopes/ValueSliderFilter.cpp 2016-03-15 09:18:55 +0000
2634@@ -25,22 +25,21 @@
2635 namespace scopes
2636 {
2637
2638-namespace experimental
2639-{
2640-
2641 ValueSliderFilter::ValueSliderFilter(internal::ValueSliderFilterImpl *impl)
2642 : FilterBase(impl)
2643 {
2644 }
2645
2646-ValueSliderFilter::UPtr ValueSliderFilter::create(std::string const& id, std::string const& label, std::string const& label_template, double min, double max)
2647+ValueSliderFilter::UPtr ValueSliderFilter::create(std::string const& id, double min, double max, double default_value, ValueSliderLabels const& labels)
2648 {
2649- return std::unique_ptr<ValueSliderFilter>(new ValueSliderFilter(new internal::ValueSliderFilterImpl(id, label, label_template, min, max)));
2650+ return std::unique_ptr<ValueSliderFilter>(new ValueSliderFilter(new internal::ValueSliderFilterImpl(id, min, max, default_value, labels)));
2651 }
2652
2653-void ValueSliderFilter::set_slider_type(SliderType tp)
2654+ValueSliderFilter::UPtr ValueSliderFilter::create(std::string const& id, double min, double max, double default_value, ValueSliderLabels const& labels, FilterGroup::SCPtr const& group)
2655 {
2656- fwd()->set_slider_type(tp);
2657+ auto filter = std::unique_ptr<ValueSliderFilter>(new ValueSliderFilter(new internal::ValueSliderFilterImpl(id, min, max, default_value, labels)));
2658+ filter->p->add_to_filter_group(group);
2659+ return filter;
2660 }
2661
2662 void ValueSliderFilter::set_default_value(double val)
2663@@ -48,11 +47,6 @@
2664 fwd()->set_default_value(val);
2665 }
2666
2667-ValueSliderFilter::SliderType ValueSliderFilter::slider_type() const
2668-{
2669- return fwd()->slider_type();
2670-}
2671-
2672 double ValueSliderFilter::default_value() const
2673 {
2674 return fwd()->default_value();
2675@@ -68,14 +62,9 @@
2676 return fwd()->max();
2677 }
2678
2679-std::string ValueSliderFilter::label() const
2680-{
2681- return fwd()->label();
2682-}
2683-
2684-std::string ValueSliderFilter::value_label_template() const
2685-{
2686- return fwd()->value_label_template();
2687+ValueSliderLabels const& ValueSliderFilter::labels() const
2688+{
2689+ return fwd()->labels();
2690 }
2691
2692 bool ValueSliderFilter::has_value(FilterState const& filter_state) const
2693@@ -103,8 +92,6 @@
2694 return dynamic_cast<internal::ValueSliderFilterImpl*>(p.get());
2695 }
2696
2697-} // namespace experimental
2698-
2699 } // namespace scopes
2700
2701 } // namespace unity
2702
2703=== added file 'src/scopes/ValueSliderLabels.cpp'
2704--- src/scopes/ValueSliderLabels.cpp 1970-01-01 00:00:00 +0000
2705+++ src/scopes/ValueSliderLabels.cpp 2016-03-15 09:18:55 +0000
2706@@ -0,0 +1,91 @@
2707+/*
2708+ * Copyright (C) 2015 Canonical Ltd
2709+ *
2710+ * This program is free software: you can redistribute it and/or modify
2711+ * it under the terms of the GNU Lesser General Public License version 3 as
2712+ * published by the Free Software Foundation.
2713+ *
2714+ * This program is distributed in the hope that it will be useful,
2715+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2716+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2717+ * GNU Lesser General Public License for more details.
2718+ *
2719+ * You should have received a copy of the GNU Lesser General Public License
2720+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2721+ *
2722+ * Authored by: Pawel Stolowski <pawel.stolowski@canonical.com>
2723+*/
2724+
2725+#include <unity/scopes/ValueSliderLabels.h>
2726+#include <unity/scopes/internal/ValueSliderLabelsImpl.h>
2727+
2728+namespace unity
2729+{
2730+
2731+namespace scopes
2732+{
2733+
2734+ValueSliderLabels::ValueSliderLabels(internal::ValueSliderLabelsImpl* pimpl)
2735+ : p(pimpl)
2736+{
2737+}
2738+
2739+ValueSliderLabels::ValueSliderLabels(std::string const& min_label, std::string const& max_label)
2740+ : p(new internal::ValueSliderLabelsImpl(min_label, max_label))
2741+{
2742+}
2743+
2744+ValueSliderLabels::ValueSliderLabels(std::string const& min_label, std::string const& max_label, ValueLabelPairList const& extra_labels)
2745+ : p(new internal::ValueSliderLabelsImpl(min_label, max_label, extra_labels))
2746+{
2747+}
2748+
2749+ValueSliderLabels::ValueSliderLabels(VariantMap const& var)
2750+ : p(new internal::ValueSliderLabelsImpl(var))
2751+{
2752+}
2753+
2754+ValueSliderLabels::ValueSliderLabels(ValueSliderLabels const& other)
2755+ : p(new internal::ValueSliderLabelsImpl(*(other.p)))
2756+{
2757+}
2758+
2759+ValueSliderLabels& ValueSliderLabels::operator=(ValueSliderLabels const& other)
2760+{
2761+ if (this != &other)
2762+ {
2763+ p.reset(new internal::ValueSliderLabelsImpl(*(other.p)));
2764+ }
2765+ return *this;
2766+}
2767+
2768+ValueSliderLabels::ValueSliderLabels(ValueSliderLabels&&) = default;
2769+ValueSliderLabels& ValueSliderLabels::operator=(ValueSliderLabels&&) = default;
2770+
2771+ValueSliderLabels::~ValueSliderLabels() = default;
2772+
2773+std::string ValueSliderLabels::min_label() const
2774+{
2775+ return p->min_label();
2776+}
2777+
2778+std::string ValueSliderLabels::max_label() const
2779+{
2780+ return p->max_label();
2781+}
2782+
2783+ValueLabelPairList ValueSliderLabels::extra_labels() const
2784+{
2785+ return p->extra_labels();
2786+}
2787+
2788+/// @cond
2789+VariantMap ValueSliderLabels::serialize() const
2790+{
2791+ return p->serialize();
2792+}
2793+/// @endcond
2794+
2795+}
2796+
2797+}
2798
2799=== modified file 'src/scopes/internal/ActivationQueryObject.cpp'
2800--- src/scopes/internal/ActivationQueryObject.cpp 2015-01-21 23:35:22 +0000
2801+++ src/scopes/internal/ActivationQueryObject.cpp 2016-03-15 09:18:55 +0000
2802@@ -71,13 +71,13 @@
2803 }
2804 catch (std::exception const& e)
2805 {
2806- BOOST_LOG(info.mw->runtime()->logger()) << "ActivationQueryBase::activate(): " << e.what();
2807+ info.mw->runtime()->logger()() << "ActivationQueryBase::activate(): " << e.what();
2808 reply_->finished(CompletionDetails(CompletionDetails::Error,
2809 string("ActivationQueryBase::activate(): ") + e.what()));
2810 }
2811 catch (...)
2812 {
2813- BOOST_LOG(info.mw->runtime()->logger()) << "ActivationQueryBase::activate(): unknown exception";
2814+ info.mw->runtime()->logger()() << "ActivationQueryBase::activate(): unknown exception";
2815 reply_->finished(CompletionDetails(CompletionDetails::Error,
2816 "ActivationQueryBase::activate(): unknown exception"));
2817 }
2818
2819=== modified file 'src/scopes/internal/CMakeLists.txt'
2820--- src/scopes/internal/CMakeLists.txt 2015-03-27 17:18:09 +0000
2821+++ src/scopes/internal/CMakeLists.txt 2016-03-15 09:18:55 +0000
2822@@ -25,6 +25,7 @@
2823 ${CMAKE_CURRENT_SOURCE_DIR}/DynamicLoader.cpp
2824 ${CMAKE_CURRENT_SOURCE_DIR}/Executor.cpp
2825 ${CMAKE_CURRENT_SOURCE_DIR}/FilterBaseImpl.cpp
2826+ ${CMAKE_CURRENT_SOURCE_DIR}/FilterGroupImpl.cpp
2827 ${CMAKE_CURRENT_SOURCE_DIR}/FilterOptionImpl.cpp
2828 ${CMAKE_CURRENT_SOURCE_DIR}/FilterStateImpl.cpp
2829 ${CMAKE_CURRENT_SOURCE_DIR}/IniSettingsSchema.cpp
2830@@ -89,6 +90,7 @@
2831 ${CMAKE_CURRENT_SOURCE_DIR}/UniqueID.cpp
2832 ${CMAKE_CURRENT_SOURCE_DIR}/Utils.cpp
2833 ${CMAKE_CURRENT_SOURCE_DIR}/ValueSliderFilterImpl.cpp
2834+ ${CMAKE_CURRENT_SOURCE_DIR}/ValueSliderLabelsImpl.cpp
2835 ${CMAKE_CURRENT_SOURCE_DIR}/VariantBuilderImpl.cpp
2836 )
2837 set(UNITY_SCOPES_LIB_SRC ${UNITY_SCOPES_LIB_SRC} ${SRC} PARENT_SCOPE)
2838
2839=== modified file 'src/scopes/internal/ChildScopesRepository.cpp'
2840--- src/scopes/internal/ChildScopesRepository.cpp 2015-04-01 11:28:32 +0000
2841+++ src/scopes/internal/ChildScopesRepository.cpp 2016-03-15 09:18:55 +0000
2842@@ -19,6 +19,7 @@
2843 #include <unity/scopes/internal/ChildScopesRepository.h>
2844 #include <unity/scopes/internal/JsonCppNode.h>
2845
2846+#include <cassert>
2847 #include <fstream>
2848 #include <set>
2849 #include <sstream>
2850@@ -26,8 +27,7 @@
2851 using namespace unity::scopes;
2852 using namespace unity::scopes::internal;
2853
2854-ChildScopesRepository::ChildScopesRepository(std::string const& repo_file_path,
2855- boost::log::sources::severity_channel_logger_mt<>& logger)
2856+ChildScopesRepository::ChildScopesRepository(std::string const& repo_file_path, Logger& logger)
2857 : repo_file_path_(repo_file_path)
2858 , logger_(logger)
2859 , have_latest_cache_(false)
2860@@ -79,9 +79,7 @@
2861 std::ofstream repo_file(repo_file_path_);
2862 if (repo_file.fail())
2863 {
2864- BOOST_LOG_SEV(logger_, Logger::Error) << "ChildScopesRepository::write_repo(): "
2865- << "Failed to open file: \"" << repo_file_path_
2866- << "\"";
2867+ logger_() << "ChildScopesRepository::write_repo(): Failed to open file: \"" << repo_file_path_ << "\"";
2868 return false;
2869 }
2870
2871@@ -104,9 +102,8 @@
2872 std::ifstream repo_file(repo_file_path_);
2873 if (repo_file.fail())
2874 {
2875- BOOST_LOG_SEV(logger_, Logger::Info) << "ChildScopesRepository::read_repo(): "
2876- << "Failed to open file: \"" << repo_file_path_
2877- << "\"";
2878+ logger_(LoggerSeverity::Info) << "ChildScopesRepository::read_repo(): "
2879+ << "Failed to open file: \"" << repo_file_path_ << "\"";
2880 return ChildScopeEnabledMap();
2881 }
2882
2883@@ -143,16 +140,13 @@
2884 }
2885 catch (std::exception const& e)
2886 {
2887- BOOST_LOG_SEV(logger_, Logger::Error) << "ChildScopesRepository::json_to_list(): "
2888- << "Exception thrown while reading json string: "
2889- << e.what();
2890+ logger_() << "ChildScopesRepository::json_to_list(): Exception thrown while reading json string: " << e.what();
2891 return ChildScopeEnabledMap();
2892 }
2893 if (json_node.type() != JsonCppNode::Array)
2894 {
2895- BOOST_LOG_SEV(logger_, Logger::Error) << "ChildScopesRepository::json_to_list(): "
2896- << "Root node of json string is not an array:"
2897- << std::endl << child_scopes_json;
2898+ logger_() << "ChildScopesRepository::json_to_list(): Root node of json string is not an array:"
2899+ << std::endl << child_scopes_json;
2900 return ChildScopeEnabledMap();
2901 }
2902
2903@@ -164,10 +158,8 @@
2904 if (!child_node->has_node("id") ||
2905 !child_node->has_node("enabled"))
2906 {
2907- BOOST_LOG_SEV(logger_, Logger::Error) << "ChildScopesRepository::json_to_list(): "
2908- << "Child node is missing a required field. "
2909- << "Skipping child node:" << std::endl
2910- << child_node->to_json_string();
2911+ logger_() << "ChildScopesRepository::json_to_list(): Child node is missing a required field. "
2912+ << "Skipping child node:" << std::endl << child_node->to_json_string();
2913 continue;
2914 }
2915 auto id_node = child_node->get_node("id");
2916@@ -176,10 +168,9 @@
2917 if (id_node->type() != JsonCppNode::String ||
2918 enabled_node->type() != JsonCppNode::Bool)
2919 {
2920- BOOST_LOG_SEV(logger_, Logger::Error) << "ChildScopesRepository::json_to_list(): "
2921- << "Child node contains an invalid value type. "
2922- << "Skipping child node:" << std::endl
2923- << child_node->to_json_string();
2924+ logger_() << "ChildScopesRepository::json_to_list(): "
2925+ << "Child node contains an invalid value type. Skipping child node:"
2926+ << std::endl << child_node->to_json_string();
2927 continue;
2928 }
2929
2930
2931=== modified file 'src/scopes/internal/FilterBaseImpl.cpp'
2932--- src/scopes/internal/FilterBaseImpl.cpp 2015-03-30 15:59:08 +0000
2933+++ src/scopes/internal/FilterBaseImpl.cpp 2016-03-15 09:18:55 +0000
2934@@ -54,6 +54,12 @@
2935 {
2936 auto it = find_or_throw("FilterBase()", var, "id");
2937 id_ = it->second.get_string();
2938+ it = var.find("title");
2939+ if (it != var.end())
2940+ {
2941+ title_ = it->second.get_string();
2942+ }
2943+
2944 it = var.find("display_hints");
2945 if (it != var.end())
2946 {
2947@@ -75,6 +81,23 @@
2948
2949 FilterBaseImpl::~FilterBaseImpl() = default;
2950
2951+void FilterBaseImpl::add_to_filter_group(FilterGroup::SCPtr const& group)
2952+{
2953+ // Filter can only belong to one group. The API guarantees this by only allowing group to be passed at Filter's construction time,
2954+ // so this assert should never be reached.
2955+ assert(filter_group_ == nullptr);
2956+ if (!group)
2957+ {
2958+ throw unity::InvalidArgumentException("FilterBaseImpl::add_to_filter_group(): invalid null group");
2959+ }
2960+ filter_group_ = group;
2961+}
2962+
2963+FilterGroup::SCPtr FilterBaseImpl::filter_group() const
2964+{
2965+ return filter_group_;
2966+}
2967+
2968 void FilterBaseImpl::set_display_hints(int hints)
2969 {
2970 // note: make sure all_flags is updated whenever new values are added to the DisplayHints enum
2971@@ -98,15 +121,33 @@
2972 return display_hints_;
2973 }
2974
2975+void FilterBaseImpl::set_title(std::string const& title)
2976+{
2977+ title_ = title;
2978+}
2979+
2980+std::string FilterBaseImpl::title() const
2981+{
2982+ return title_;
2983+}
2984+
2985 VariantMap FilterBaseImpl::serialize() const
2986 {
2987 VariantMap vm;
2988 vm["id"] = id_;
2989+ if (title_.size() > 0)
2990+ {
2991+ vm["title"] = title_;
2992+ }
2993 if (display_hints_ != FilterBase::DisplayHints::Default)
2994 {
2995 vm["display_hints"] = static_cast<int>(display_hints_);
2996 }
2997 vm["filter_type"] = filter_type();
2998+ if (filter_group_)
2999+ {
3000+ vm["filter_group"] = filter_group_->id();
3001+ }
3002 serialize(vm);
3003 return vm;
3004 }
3005@@ -170,12 +211,28 @@
3006 return var;
3007 }
3008
3009-Filters FilterBaseImpl::deserialize_filters(VariantArray const& var)
3010+Filters FilterBaseImpl::deserialize_filters(VariantArray const& var, std::map<std::string, FilterGroup::SCPtr> const& groups)
3011 {
3012 Filters filters;
3013 for (auto const& f: var)
3014 {
3015- filters.push_back(FilterBaseImpl::deserialize(f.get_dict()));
3016+ auto const data = f.get_dict();
3017+ auto filter = FilterBaseImpl::deserialize(data);
3018+ auto grit = data.find("filter_group");
3019+ if (grit != data.end())
3020+ {
3021+ auto const group_id = grit->second.get_string();
3022+ auto it = groups.find(group_id);
3023+ if (it != groups.end())
3024+ {
3025+ filter->p->add_to_filter_group(it->second);
3026+ }
3027+ else
3028+ {
3029+ throw unity::LogicException("FilterBaseImpl::deserialize_filters(): Invalid group '" + group_id + "' for filter '" + filter->id() + "'");
3030+ }
3031+ }
3032+ filters.push_back(filter);
3033 }
3034 return filters;
3035 }
3036
3037=== added file 'src/scopes/internal/FilterGroupImpl.cpp'
3038--- src/scopes/internal/FilterGroupImpl.cpp 1970-01-01 00:00:00 +0000
3039+++ src/scopes/internal/FilterGroupImpl.cpp 2016-03-15 09:18:55 +0000
3040@@ -0,0 +1,97 @@
3041+/*
3042+ * Copyright (C) 2016 Canonical Ltd
3043+ *
3044+ * This program is free software: you can redistribute it and/or modify
3045+ * it under the terms of the GNU Lesser General Public License version 3 as
3046+ * published by the Free Software Foundation.
3047+ *
3048+ * This program is distributed in the hope that it will be useful,
3049+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3050+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3051+ * GNU Lesser General Public License for more details.
3052+ *
3053+ * You should have received a copy of the GNU Lesser General Public License
3054+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3055+ *
3056+ * Authored by: Pawel Stolowski <pawel.stolowski@canonical.com>
3057+*/
3058+
3059+#include <unity/scopes/internal/FilterGroupImpl.h>
3060+#include <unity/UnityExceptions.h>
3061+#include <unity/scopes/FilterState.h>
3062+#include <unity/scopes/internal/Utils.h>
3063+
3064+namespace unity
3065+{
3066+
3067+namespace scopes
3068+{
3069+
3070+namespace internal
3071+{
3072+
3073+FilterGroupImpl::FilterGroupImpl(std::string const& id, std::string const& label)
3074+ : id_(id),
3075+ label_(label)
3076+{
3077+}
3078+
3079+std::string FilterGroupImpl::id() const
3080+{
3081+ return id_;
3082+}
3083+
3084+std::string FilterGroupImpl::label() const
3085+{
3086+ return label_;
3087+}
3088+
3089+VariantArray FilterGroupImpl::serialize_filter_groups(Filters const& filters)
3090+{
3091+ std::map<std::string, FilterGroup::SCPtr> group_lookup;
3092+ VariantArray va;
3093+ for (auto const& filter: filters)
3094+ {
3095+ auto grp = filter->filter_group();
3096+ if (grp)
3097+ {
3098+ auto it = group_lookup.find(grp->id());
3099+ if (it == group_lookup.end())
3100+ {
3101+ group_lookup[grp->id()] = grp;
3102+ VariantMap grpvar;
3103+ grpvar["id"] = grp->id();
3104+ grpvar["label"] = grp->label();
3105+ va.push_back(Variant(grpvar));
3106+ }
3107+ else
3108+ {
3109+ if (it->second != grp)
3110+ {
3111+ throw unity::LogicException("FilterGroupImpl::serialize_filter_groups(): duplicate FilterGroup definitions for group id '" + grp->id() + "'");
3112+ }
3113+ }
3114+ }
3115+ }
3116+ return va;
3117+}
3118+
3119+std::map<std::string, FilterGroup::SCPtr> FilterGroupImpl::deserialize_filter_groups(VariantArray const& var)
3120+{
3121+ std::map<std::string, FilterGroup::SCPtr> groups;
3122+ for (auto it = var.begin(); it != var.end(); it++)
3123+ {
3124+ auto const grvar = it->get_dict();
3125+ auto const id = find_or_throw("FilterGroup::deserialize_filter_groups", grvar, "id")->second.get_string();
3126+ auto const label = find_or_throw("FilterGroup::deserialize_filter_groups", grvar, "label")->second.get_string();
3127+ auto group = FilterGroup::create(id, label);
3128+ groups[id] = group;
3129+ }
3130+ return groups;
3131+}
3132+
3133+} // namespace internal
3134+
3135+} // namespace scopes
3136+
3137+} // namespace unity
3138
3139=== modified file 'src/scopes/internal/FilterOptionImpl.cpp'
3140--- src/scopes/internal/FilterOptionImpl.cpp 2014-05-15 03:23:43 +0000
3141+++ src/scopes/internal/FilterOptionImpl.cpp 2016-03-15 09:18:55 +0000
3142@@ -31,7 +31,8 @@
3143
3144 FilterOptionImpl::FilterOptionImpl(std::string const& id, std::string const& label)
3145 : id_(id),
3146- label_(label)
3147+ label_(label),
3148+ default_value_(false)
3149 {
3150 if (id_.empty())
3151 {
3152@@ -53,6 +54,16 @@
3153 return label_;
3154 }
3155
3156+void FilterOptionImpl::set_default_value(bool default_value)
3157+{
3158+ default_value_ = default_value;
3159+}
3160+
3161+bool FilterOptionImpl::default_value() const
3162+{
3163+ return default_value_;
3164+}
3165+
3166 } // namespace internal
3167
3168 } // namespace scopes
3169
3170=== modified file 'src/scopes/internal/Logger.cpp'
3171--- src/scopes/internal/Logger.cpp 2015-03-02 13:18:28 +0000
3172+++ src/scopes/internal/Logger.cpp 2016-03-15 09:18:55 +0000
3173@@ -18,33 +18,14 @@
3174
3175 #include <unity/scopes/internal/Logger.h>
3176
3177-#include <boost/log/attributes.hpp>
3178-#include <boost/log/core.hpp>
3179-#include <boost/log/expressions.hpp>
3180-#include <boost/log/sources/record_ostream.hpp>
3181-#include <boost/log/support/date_time.hpp>
3182-#include <boost/log/trivial.hpp>
3183-#include <boost/phoenix/bind.hpp>
3184-
3185-#if (BOOST_VERSION / 100000 == 1) && (((BOOST_VERSION / 100) % 1000) < 56)
3186-#include <boost/utility/empty_deleter.hpp>
3187-typedef boost::empty_deleter NullDeleter;
3188-#else
3189-#include <boost/core/null_deleter.hpp>
3190-typedef boost::null_deleter NullDeleter;
3191-#endif
3192-
3193 #include <unity/UnityExceptions.h>
3194
3195+#include <cassert>
3196+#include <chrono>
3197+#include <iomanip>
3198+
3199 using namespace std;
3200
3201-namespace logging = boost::log;
3202-namespace sinks = boost::log::sinks;
3203-namespace src = boost::log::sources;
3204-namespace attrs = boost::log::attributes;
3205-namespace expr = boost::log::expressions;
3206-namespace keywords = boost::log::keywords;
3207-
3208 namespace unity
3209 {
3210
3211@@ -57,214 +38,158 @@
3212 namespace
3213 {
3214
3215-static array<string, Logger::LastChannelEnum_> const channel_names = {{"IPC"}};
3216+static array<string, 5> const severities = {{"INFO", "WARNING", "ERROR", "FATAL", "TRACE"}};
3217
3218-string const& to_severity(int s)
3219+static array<pair<string, LoggerChannel>, int(LoggerChannel::LastChannelEnum_)> const channel_names =
3220 {
3221- static array<string, 5> const severities = {{"INFO", "WARNING", "ERROR", "FATAL", "TRACE"}};
3222- static string const unknown = "UNKNOWN";
3223+ pair<string, LoggerChannel>{"", LoggerChannel::DefaultChannel},
3224+ pair<string, LoggerChannel>{"IPC", LoggerChannel::IPC}
3225+};
3226
3227- if (s < 0 || s >= static_cast<int>(severities.size()))
3228- {
3229- return unknown;
3230- }
3231- return severities[s];
3232-}
3233-}
3234+} // namespace
3235
3236 // Instantiate a logger for the scope/client with the given ID.
3237
3238-Logger::Logger(string const& scope_id)
3239- : scope_id_(scope_id)
3240- , logger_(keywords::severity = Logger::Error)
3241- , severity_(Logger::Info)
3242-{
3243- namespace ph = std::placeholders;
3244-
3245- assert(!scope_id_.empty());
3246-
3247- logger_.add_attribute("TimeStamp", attrs::local_clock());
3248-
3249- // Create a channel logger for each channel.
3250- for (auto&& name : channel_names)
3251- {
3252- auto clogger = boost::log::sources::severity_channel_logger_mt<>(keywords::severity = Logger::Trace,
3253- keywords::channel = name);
3254- clogger.add_attribute("TimeStamp", attrs::local_clock());
3255- channel_loggers_[name] = make_pair(clogger, false);
3256- }
3257-
3258- // Set up sink that logs to std::clog.
3259- clog_sink_ = boost::make_shared<ClogSinkT>();
3260- clog_sink_->set_formatter(bind(&Logger::formatter, this, ph::_1, ph::_2));
3261- boost::shared_ptr<std::ostream> console_stream(&std::clog, NullDeleter());
3262- clog_sink_->locked_backend()->add_stream(console_stream);
3263- clog_sink_->locked_backend()->auto_flush(true);
3264- logging::core::get()->add_sink(clog_sink_);
3265-
3266- set_severity_threshold(severity_);
3267-}
3268-
3269-Logger::~Logger()
3270-{
3271- lock_guard<mutex> lock(mutex_);
3272-
3273- if (clog_sink_)
3274- {
3275- logging::core::get()->remove_sink(clog_sink_);
3276- clog_sink_->stop();
3277- clog_sink_->flush();
3278- }
3279- else
3280- {
3281- logging::core::get()->remove_sink(file_sink_);
3282- file_sink_->stop();
3283- file_sink_->flush();
3284- }
3285-}
3286-
3287-Logger::operator boost::log::sources::severity_channel_logger_mt<>&()
3288-{
3289- return logger_; // No lock needed, immutable
3290-}
3291-
3292-src::severity_channel_logger_mt<>& Logger::operator()(Channel c)
3293-{
3294- // No lock needed: channel_loggers_ is immutable, and the boolean is atomic.
3295- return channel_loggers_[channel_names[c]].first;
3296-}
3297-
3298-bool Logger::set_channel(Channel c, bool enable)
3299-{
3300- auto it = channel_loggers_.find(channel_names[c]);
3301- assert(it != channel_loggers_.end());
3302- bool was_enabled = it->second.second.exchange(enable);
3303- return was_enabled;
3304+Logger::Logger(string const& id, ostream& outstream)
3305+ : id_(id)
3306+ , outstream_(outstream)
3307+ , severity_threshold_(LoggerSeverity::Info) // By default, log all severities
3308+{
3309+ // Channels are disabled by default.
3310+ for (auto& e : enabled_)
3311+ {
3312+ e = false;
3313+ }
3314+ // Except for the default channel.
3315+ enabled_[0] = true;
3316+}
3317+
3318+// Default writes to the default channel at severity Error.
3319+
3320+LogStream Logger::operator()()
3321+{
3322+ if (LoggerSeverity::Error >= severity_threshold_)
3323+ {
3324+ return LogStream(outstream_, id_, LoggerSeverity::Error, LoggerChannel::DefaultChannel);
3325+ }
3326+ return LogStream(); // Null writer
3327+}
3328+
3329+LogStream Logger::operator()(LoggerSeverity s)
3330+{
3331+ if (s >= severity_threshold_)
3332+ {
3333+ return LogStream(outstream_, id_, s, LoggerChannel::DefaultChannel);
3334+ }
3335+ return LogStream(); // Null writer
3336+}
3337+
3338+LogStream Logger::operator()(LoggerChannel c)
3339+{
3340+ if (enabled_[int(c)])
3341+ {
3342+ return LogStream(outstream_, id_, LoggerSeverity::Trace, c);
3343+ }
3344+ return LogStream(); // Null writer
3345+}
3346+
3347+bool Logger::set_channel(LoggerChannel c, bool enable)
3348+{
3349+ return enabled_[int(c)].exchange(enable);
3350 }
3351
3352 bool Logger::set_channel(string channel_name, bool enable)
3353 {
3354- auto it = channel_loggers_.find(channel_name);
3355- if (it == channel_loggers_.end())
3356- {
3357- throw InvalidArgumentException("Logger::set_channel(): invalid channel name: " + channel_name);
3358- }
3359- bool was_enabled = it->second.second.exchange(enable);
3360- return was_enabled;
3361-}
3362-
3363-void Logger::enable_channels(vector<string> const& names)
3364-{
3365- exception_ptr ep;
3366- for (auto&& name : names)
3367- {
3368- try
3369- {
3370- set_channel(name, true);
3371- }
3372- catch (InvalidArgumentException& e)
3373- {
3374- ep = ep ? make_exception_ptr(current_exception()) : e.remember(ep);
3375- }
3376- }
3377- if (ep)
3378- {
3379- rethrow_exception(ep);
3380- }
3381-}
3382-
3383-void Logger::set_log_file(string const& path, int rotation_size, int dir_size)
3384-{
3385- namespace ph = std::placeholders;
3386-
3387- FileSinkPtr s =
3388- boost::make_shared<FileSinkT>(keywords::file_name = path + "-%N.log", keywords::rotation_size = rotation_size);
3389-
3390- string parent = boost::filesystem::path(path).parent_path().native();
3391- s->locked_backend()->set_file_collector(sinks::file::make_collector(
3392- keywords::target = parent, keywords::max_size = dir_size, keywords::min_free_space = 1024 * 1024 * 5));
3393- try
3394- {
3395- s->locked_backend()->scan_for_files();
3396- }
3397- catch (std::exception const& e)
3398- {
3399- BOOST_LOG_SEV(logger_, Warning) << "RuntimeImpl::Logger(): log rotation failed (path = " << parent
3400- << "): " << e.what();
3401- return;
3402- }
3403- catch (...)
3404- {
3405- BOOST_LOG_SEV(logger_, Warning) << "RuntimeImpl::Logger(): log rotation failed (path = " << parent
3406- << "): unknown exception";
3407- return;
3408- }
3409-
3410- {
3411- lock_guard<mutex> lock(mutex_);
3412-
3413- if (clog_sink_)
3414- {
3415- logging::core::get()->remove_sink(clog_sink_);
3416- clog_sink_ = nullptr;
3417- }
3418- else
3419- {
3420- logging::core::get()->remove_sink(file_sink_);
3421- }
3422-
3423- file_sink_ = s;
3424- file_sink_->locked_backend()->auto_flush(true);
3425- file_sink_->set_formatter(bind(&Logger::formatter, this, ph::_1, ph::_2));
3426- logging::core::get()->add_sink(file_sink_);
3427- }
3428- set_severity_threshold(severity_);
3429-}
3430-
3431-Logger::Severity Logger::set_severity_threshold(Logger::Severity s)
3432-{
3433- auto old_s = severity_.exchange(s);
3434-
3435- lock_guard<mutex> lock(mutex_);
3436-
3437- auto filter = boost::phoenix::bind(&Logger::filter, this, severity.or_none(), channel.or_none());
3438- if (clog_sink_)
3439- {
3440- clog_sink_->set_filter(filter);
3441- }
3442- else
3443- {
3444- file_sink_->set_filter(filter);
3445- }
3446-
3447- return old_s;
3448-}
3449-
3450-bool Logger::filter(logging::value_ref<int, tag::severity> const& level,
3451- logging::value_ref<string, tag::channel> const& channel)
3452-{
3453- if (level.get() < static_cast<int>(severity_)) // atomic
3454- {
3455- return false;
3456- }
3457- if (channel.get().empty())
3458- {
3459- return true;
3460- }
3461- // No lock needed: channel_loggers_ is immutable, and the boolean is atomic.
3462- auto it = channel_loggers_.find(channel.get());
3463- assert(it != channel_loggers_.end());
3464- return it->second.second;
3465-}
3466-
3467-void Logger::formatter(logging::record_view const& rec, logging::formatting_ostream& strm)
3468-{
3469- string channel = expr::attr<string>("Channel")(rec).get();
3470-
3471- string prefix = channel.empty() ? to_severity(expr::attr<int>("Severity")(rec).get()) : channel;
3472-
3473- strm << "[" << expr::format_date_time<boost::posix_time::ptime>("TimeStamp", "%Y-%m-%d %H:%M:%S.%f")(rec) << "] "
3474- << prefix << ": " << scope_id_ << ": " << rec[expr::smessage];
3475+ for (auto const& p : channel_names)
3476+ {
3477+ if (!p.first.empty() && channel_name == p.first)
3478+ {
3479+ return set_channel(p.second, enable);
3480+ }
3481+ }
3482+ throw InvalidArgumentException("Logger::set_channel(): invalid channel name: \"" + channel_name + "\"");
3483+}
3484+
3485+LoggerSeverity Logger::set_severity_threshold(LoggerSeverity s)
3486+{
3487+ return severity_threshold_.exchange(s);
3488+}
3489+
3490+namespace
3491+{
3492+
3493+// Null streambuf implementation that always reports success.
3494+// This allows the operator<<() functions to inject into a stream without
3495+// having to check in each function whether we actually want to log something.
3496+
3497+template <class cT, class traits = std::char_traits<cT>>
3498+class NullBuf : public std::basic_streambuf<cT, traits>
3499+{
3500+ typename traits::int_type overflow(typename traits::int_type c)
3501+ {
3502+ return traits::not_eof(c); // Indicate success
3503+ }
3504+};
3505+
3506+static string const null_id;
3507+static NullBuf<char> null_buf;
3508+static ostream null_stream(&null_buf);
3509+
3510+} // namespace
3511+
3512+LogStream::LogStream() // Doesn't log anything
3513+ : id_(null_id)
3514+ , outstream_(null_stream)
3515+ , severity_(static_cast<LoggerSeverity>(0))
3516+ , channel_(static_cast<LoggerChannel>(0))
3517+{
3518+}
3519+
3520+LogStream::LogStream(ostream& outstream, string const& id, LoggerSeverity s, LoggerChannel c)
3521+ : id_(id)
3522+ , outstream_(outstream)
3523+ , severity_(s)
3524+ , channel_(c)
3525+{
3526+}
3527+
3528+namespace
3529+{
3530+
3531+string get_time()
3532+{
3533+ auto now = chrono::system_clock::now();
3534+ auto curr_t = chrono::system_clock::to_time_t(now);
3535+ auto millisecs = chrono::duration_cast<chrono::milliseconds>(now.time_since_epoch()).count() % 1000;
3536+
3537+ struct tm result;
3538+ localtime_r(&curr_t, &result);
3539+
3540+ // Should use std::put_time(&result, "%F %T') here, but gcc 4.9 doesn't provide it.
3541+ char buf[]{"yyyy-mm-dd hh:mm:ss"};
3542+ strftime(buf, sizeof(buf), "%F %T", &result);
3543+ stringstream s;
3544+ s << buf << "." << setw(3) << setfill('0') << millisecs;
3545+ return s.str();
3546+}
3547+
3548+} // namespace
3549+
3550+LogStream::~LogStream()
3551+{
3552+ string msg = str();
3553+ if (msg.empty())
3554+ {
3555+ return;
3556+ }
3557+ // Something was logged. Accumulate all the details in an output string.
3558+ string prefix = channel_ != LoggerChannel::DefaultChannel
3559+ ? channel_names[int(channel_)].first
3560+ : severities[int(severity_)];
3561+ string output = "[" + get_time() + "] " + prefix + ": " + id_ + ": " + msg + "\n";
3562+
3563+ // Write contents with a single insertion to avoid interleaving of messages from different threads.
3564+ outstream_ << output;
3565 }
3566
3567 } // namespace internal
3568
3569=== modified file 'src/scopes/internal/OptionSelectorFilterImpl.cpp'
3570--- src/scopes/internal/OptionSelectorFilterImpl.cpp 2015-11-12 14:20:36 +0000
3571+++ src/scopes/internal/OptionSelectorFilterImpl.cpp 2016-03-15 09:18:55 +0000
3572@@ -17,6 +17,7 @@
3573 */
3574
3575 #include <unity/scopes/internal/OptionSelectorFilterImpl.h>
3576+#include <unity/scopes/internal/FilterOptionImpl.h>
3577 #include <unity/scopes/FilterState.h>
3578 #include <unity/scopes/ScopeExceptions.h>
3579 #include <unity/UnityExceptions.h>
3580@@ -75,6 +76,10 @@
3581 VariantMap vm;
3582 vm["id"] = opt->id();
3583 vm["label"] = opt->label();
3584+ if (opt->default_value())
3585+ {
3586+ vm["default"] = Variant(true);
3587+ }
3588 ops.push_back(Variant(vm));
3589 }
3590 var["label"] = label_;
3591@@ -111,7 +116,14 @@
3592 auto opt_id = it->second.get_string();
3593 it = optvar.find("label");
3594 throw_on_missing(it, optvar.end(), "option label");
3595- add_option(opt_id, it->second.get_string());
3596+ auto const label = it->second.get_string();
3597+ bool default_val = false;
3598+ it = optvar.find("default");
3599+ if (it != optvar.end() && it->second.get_bool())
3600+ {
3601+ default_val = true;
3602+ }
3603+ add_option(opt_id, label, default_val);
3604 }
3605 }
3606
3607@@ -120,18 +132,23 @@
3608 return "option_selector";
3609 }
3610
3611-FilterOption::SCPtr OptionSelectorFilterImpl::add_option(std::string const& id, std::string const& label)
3612+FilterOption::SCPtr OptionSelectorFilterImpl::add_option(std::string const& id, std::string const& label, bool default_value)
3613 {
3614- try
3615- {
3616- auto opt = std::shared_ptr<FilterOption>(new FilterOption(id, label));
3617- options_.push_back(opt);
3618- return opt;
3619- }
3620- catch (...)
3621- {
3622- throw ResourceException("OptionSelectorFilter(): cannot create FilterOption");
3623- }
3624+ auto opt = std::shared_ptr<FilterOption>(new FilterOption(id, label));
3625+ // if it's not a multi-selection filter, then there can only be a single option selected by default
3626+ if (default_value && !multi_select_)
3627+ {
3628+ for (auto const& o: options_)
3629+ {
3630+ if (o->default_value())
3631+ {
3632+ throw unity::LogicException("OptionSelectorFilter::add_option(): only one option with default value 'true' allowed for a single-selection OptionSelectorFilter");
3633+ }
3634+ }
3635+ }
3636+ opt->p->set_default_value(default_value);
3637+ options_.push_back(opt);
3638+ return opt;
3639 }
3640
3641 int OptionSelectorFilterImpl::num_of_options() const
3642@@ -183,6 +200,17 @@
3643 // via a canned query from another scope, we shouldn't break this scope on it.
3644 }
3645 }
3646+ else
3647+ {
3648+ // we don't have this filter in the state object, so give defaults back
3649+ for (auto const& opt: options_)
3650+ {
3651+ if (opt->default_value())
3652+ {
3653+ opts.insert(opt);
3654+ }
3655+ }
3656+ }
3657 return opts;
3658 }
3659
3660
3661=== modified file 'src/scopes/internal/PreviewQueryObject.cpp'
3662--- src/scopes/internal/PreviewQueryObject.cpp 2015-01-20 02:14:29 +0000
3663+++ src/scopes/internal/PreviewQueryObject.cpp 2016-03-15 09:18:55 +0000
3664@@ -94,7 +94,7 @@
3665 lock_guard<mutex> lock(mutex_);
3666 pushable_ = false;
3667 }
3668- BOOST_LOG(info.mw->runtime()->logger()) << "PreviewQueryBase::run(): " << e.what();
3669+ info.mw->runtime()->logger()() << "PreviewQueryBase::run(): " << e.what();
3670 reply_->finished(CompletionDetails(CompletionDetails::Error, string("PreviewQueryBase::run(): ") + e.what()));
3671 }
3672 catch (...)
3673@@ -103,7 +103,7 @@
3674 lock_guard<mutex> lock(mutex_);
3675 pushable_ = false;
3676 }
3677- BOOST_LOG(info.mw->runtime()->logger()) << "PreviewQueryBase::run(): unknown exception";
3678+ info.mw->runtime()->logger()() << "PreviewQueryBase::run(): unknown exception";
3679 reply_->finished(CompletionDetails(CompletionDetails::Error, "PreviewQueryBase::run(): unknown exception"));
3680 }
3681 }
3682
3683=== modified file 'src/scopes/internal/QueryCtrlImpl.cpp'
3684--- src/scopes/internal/QueryCtrlImpl.cpp 2015-01-26 08:20:45 +0000
3685+++ src/scopes/internal/QueryCtrlImpl.cpp 2016-03-15 09:18:55 +0000
3686@@ -78,7 +78,7 @@
3687 }
3688 catch (std::exception const& e)
3689 {
3690- BOOST_LOG(reply_proxy_->mw_base()->runtime()->logger()) << e.what();
3691+ reply_proxy_->mw_base()->runtime()->logger()() << e.what();
3692 }
3693 }
3694
3695
3696=== modified file 'src/scopes/internal/QueryObject.cpp'
3697--- src/scopes/internal/QueryObject.cpp 2015-04-10 10:00:19 +0000
3698+++ src/scopes/internal/QueryObject.cpp 2016-03-15 09:18:55 +0000
3699@@ -128,7 +128,7 @@
3700 lock_guard<mutex> lock(mutex_);
3701 pushable_ = false;
3702 }
3703- BOOST_LOG(info.mw->runtime()->logger()) << "QueryBase::run(): " << e.what();
3704+ info.mw->runtime()->logger()() << "QueryBase::run(): " << e.what();
3705 reply_->finished(CompletionDetails(CompletionDetails::Error, string("QueryBase::run(): ") + e.what()));
3706 }
3707 catch (...)
3708@@ -137,7 +137,7 @@
3709 lock_guard<mutex> lock(mutex_);
3710 pushable_ = false;
3711 }
3712- BOOST_LOG(info.mw->runtime()->logger()) << "QueryBase::run(): unknown exception";
3713+ info.mw->runtime()->logger()() << "QueryBase::run(): unknown exception";
3714 reply_->finished(CompletionDetails(CompletionDetails::Error, "QueryBase::run(): unknown exception"));
3715 }
3716 }
3717@@ -171,7 +171,7 @@
3718 }
3719 catch (std::exception const& e)
3720 {
3721- BOOST_LOG(info.mw->runtime()->logger()) << "QueryBase::cancelled(): " << e.what();
3722+ info.mw->runtime()->logger()() << "QueryBase::cancelled(): " << e.what();
3723 // Deliberately no error completion here. On the client side, we short-cut the cancelled()
3724 // callback locally, which unregisters the servant for the cancel message and assumes that
3725 // cancellation will work, passing a Cancelled status, even if cancellation throws in the scope.
3726@@ -182,7 +182,7 @@
3727 }
3728 catch (...)
3729 {
3730- BOOST_LOG(info.mw->runtime()->logger()) << "QueryBase::cancelled(): unknown exception";
3731+ info.mw->runtime()->logger()() << "QueryBase::cancelled(): unknown exception";
3732 // Same caveat as for std::exception here.
3733 reply_->finished(CompletionDetails(CompletionDetails::Cancelled, ""));
3734 }
3735
3736=== modified file 'src/scopes/internal/RangeInputFilterImpl.cpp'
3737--- src/scopes/internal/RangeInputFilterImpl.cpp 2015-11-12 14:20:36 +0000
3738+++ src/scopes/internal/RangeInputFilterImpl.cpp 2016-03-15 09:18:55 +0000
3739@@ -1,5 +1,5 @@
3740 /*
3741- * Copyright (C) 2014 Canonical Ltd
3742+ * Copyright (C) 2015 Canonical Ltd
3743 *
3744 * This program is free software: you can redistribute it and/or modify
3745 * it under the terms of the GNU Lesser General Public License version 3 as
3746@@ -31,11 +31,19 @@
3747 namespace internal
3748 {
3749
3750-RangeInputFilterImpl::RangeInputFilterImpl(std::string const& id, std::string const& start_label, std::string const& end_label, std::string const& unit_label)
3751+RangeInputFilterImpl::RangeInputFilterImpl(std::string const& id,
3752+ Variant const& default_start_value, Variant const& default_end_value,
3753+ std::string const& start_prefix_label, std::string const& start_postfix_label,
3754+ std::string const& central_label,
3755+ std::string const& end_prefix_label, std::string const& end_postfix_label)
3756 : FilterBaseImpl(id),
3757- start_label_(start_label),
3758- end_label_(end_label),
3759- unit_label_(unit_label)
3760+ default_start_value_(default_start_value),
3761+ default_end_value_(default_end_value),
3762+ start_prefix_label_(start_prefix_label),
3763+ start_postfix_label_(start_postfix_label),
3764+ end_prefix_label_(end_prefix_label),
3765+ end_postfix_label_(end_postfix_label),
3766+ central_label_(central_label)
3767 {
3768 }
3769
3770@@ -52,19 +60,39 @@
3771 return filter;
3772 }
3773
3774-std::string RangeInputFilterImpl::start_label() const
3775-{
3776- return start_label_;
3777-}
3778-
3779-std::string RangeInputFilterImpl::end_label() const
3780-{
3781- return end_label_;
3782-}
3783-
3784-std::string RangeInputFilterImpl::unit_label() const
3785-{
3786- return unit_label_;
3787+std::string RangeInputFilterImpl::start_prefix_label() const
3788+{
3789+ return start_prefix_label_;
3790+}
3791+
3792+std::string RangeInputFilterImpl::start_postfix_label() const
3793+{
3794+ return start_postfix_label_;
3795+}
3796+
3797+std::string RangeInputFilterImpl::end_prefix_label() const
3798+{
3799+ return end_prefix_label_;
3800+}
3801+
3802+std::string RangeInputFilterImpl::end_postfix_label() const
3803+{
3804+ return end_postfix_label_;
3805+}
3806+
3807+std::string RangeInputFilterImpl::central_label() const
3808+{
3809+ return central_label_;
3810+}
3811+
3812+Variant RangeInputFilterImpl::default_start_value() const
3813+{
3814+ return default_start_value_;
3815+}
3816+
3817+Variant RangeInputFilterImpl::default_end_value() const
3818+{
3819+ return default_end_value_;
3820 }
3821
3822 bool RangeInputFilterImpl::has_value(FilterState const& filter_state, unsigned int index) const
3823@@ -114,24 +142,56 @@
3824 {
3825 }
3826 }
3827- throw unity::scopes::NotFoundException("RangeInputFilterImpl::get_value(): invalid index for filter '" + id() + "'",
3828+ throw NotFoundException("RangeInputFilterImpl::get_value(): invalid index for filter '" + id() + "'",
3829 std::to_string(index));
3830 }
3831
3832 double RangeInputFilterImpl::start_value(FilterState const& filter_state) const
3833 {
3834- return get_value(filter_state, 0);
3835+ try
3836+ {
3837+ return get_value(filter_state, 0);
3838+ }
3839+ catch (unity::scopes::NotFoundException const&)
3840+ {
3841+ if (default_start_value_.which() == Variant::Type::Double)
3842+ {
3843+ return default_start_value_.get_double();
3844+ }
3845+ if (default_end_value_.which() == Variant::Type::Int)
3846+ {
3847+ return default_start_value_.get_int();
3848+ }
3849+ }
3850+ throw NotFoundException("RangeInputFilterImpl::start_value(): start value is not set for filter", id());
3851 }
3852
3853 double RangeInputFilterImpl::end_value(FilterState const& filter_state) const
3854 {
3855- return get_value(filter_state, 1);
3856+ try
3857+ {
3858+ return get_value(filter_state, 1);
3859+ }
3860+ catch (unity::scopes::NotFoundException const&)
3861+ {
3862+ if (default_end_value_.which() == Variant::Type::Double)
3863+ {
3864+ return default_end_value_.get_double();
3865+ }
3866+ if (default_end_value_.which() == Variant::Type::Int)
3867+ {
3868+ return default_end_value_.get_int();
3869+ }
3870+ }
3871+ throw NotFoundException("RangeInputFilterImpl::end_value(): end value is not set for filter", id());
3872 }
3873
3874 void RangeInputFilterImpl::check_type(Variant const& val, std::string const& filter_id, std::string const& varname)
3875 {
3876 if (val.which() == Variant::Type::Int || val.which() == Variant::Type::Double || val.is_null())
3877+ {
3878 return;
3879+ }
3880 std::stringstream err;
3881 err << "RangeInputFilterImpl::check_type(): Invalid variant type for " << varname << ", filter '" << filter_id << "'";
3882 throw unity::InvalidArgumentException(err.str());
3883@@ -178,19 +238,31 @@
3884
3885 void RangeInputFilterImpl::serialize(VariantMap& var) const
3886 {
3887- var["start_label"] = start_label_;
3888- var["end_label"] = end_label_;
3889- var["unit_label"] = unit_label_;
3890+ var["default_start_value"] = default_start_value_;
3891+ var["default_end_value"] = default_end_value_;
3892+ var["start_prefix_label"] = start_prefix_label_;
3893+ var["start_postfix_label"] = start_postfix_label_;
3894+ var["end_prefix_label"] = end_prefix_label_;
3895+ var["end_postfix_label"] = end_postfix_label_;
3896+ var["central_label"] = central_label_;
3897 }
3898
3899 void RangeInputFilterImpl::deserialize(VariantMap const& var)
3900 {
3901- auto it = find_or_throw("RangeInputFilterImpl::deserialize()", var, "start_label");
3902- start_label_ = it->second.get_string();
3903- it = find_or_throw("RangeInputFilterImpl::deserialize()", var, "end_label");
3904- end_label_ = it->second.get_string();
3905- it = find_or_throw("RangeInputFilterImpl::deserialize()", var, "unit_label");
3906- unit_label_ = it->second.get_string();
3907+ auto it = find_or_throw("RangeInputFilterImpl::deserialize()", var, "start_prefix_label");
3908+ start_prefix_label_ = it->second.get_string();
3909+ it = find_or_throw("RangeInputFilterImpl::deserialize()", var, "start_postfix_label");
3910+ start_postfix_label_ = it->second.get_string();
3911+ it = find_or_throw("RangeInputFilterImpl::deserialize()", var, "end_prefix_label");
3912+ end_prefix_label_ = it->second.get_string();
3913+ it = find_or_throw("RangeInputFilterImpl::deserialize()", var, "end_postfix_label");
3914+ end_postfix_label_ = it->second.get_string();
3915+ it = find_or_throw("RangeInputFilterImpl::deserialize()", var, "central_label");
3916+ central_label_ = it->second.get_string();
3917+ it = find_or_throw("RangeInputFilterImpl::deserialize()", var, "default_start_value");
3918+ default_start_value_ = it->second;
3919+ it = find_or_throw("RangeInputFilterImpl::deserialize()", var, "default_end_value");
3920+ default_end_value_ = it->second;
3921 }
3922
3923 void RangeInputFilterImpl::validate_display_hints() const
3924
3925=== modified file 'src/scopes/internal/RatingFilterImpl.cpp'
3926--- src/scopes/internal/RatingFilterImpl.cpp 2014-05-15 14:51:39 +0000
3927+++ src/scopes/internal/RatingFilterImpl.cpp 2016-03-15 09:18:55 +0000
3928@@ -58,7 +58,7 @@
3929 {
3930 }
3931
3932-FilterOption::SCPtr RatingFilterImpl::add_option(std::string const& id, std::string const& label)
3933+FilterOption::SCPtr RatingFilterImpl::add_option(std::string const& id, std::string const& label, bool /* default_value */)
3934 {
3935 if (num_of_options() < max_rating)
3936 {
3937
3938=== modified file 'src/scopes/internal/RegistryObject.cpp'
3939--- src/scopes/internal/RegistryObject.cpp 2015-12-08 01:02:15 +0000
3940+++ src/scopes/internal/RegistryObject.cpp 2016-03-15 09:18:55 +0000
3941@@ -91,7 +91,7 @@
3942 }
3943 catch (std::exception const& e)
3944 {
3945- BOOST_LOG(logger_) << "RegistryObject(): failed to create registry publisher: " << e.what();
3946+ logger_() << "RegistryObject(): failed to create registry publisher: " << e.what();
3947 }
3948 }
3949 }
3950@@ -120,7 +120,7 @@
3951 }
3952 catch(std::exception const& e)
3953 {
3954- BOOST_LOG(logger_) << "RegistryObject::~RegistryObject(): " << e.what();
3955+ logger_() << "RegistryObject::~RegistryObject(): " << e.what();
3956 }
3957 }
3958 }
3959@@ -154,7 +154,7 @@
3960 }
3961 catch (std::exception const& e)
3962 {
3963- BOOST_LOG(logger_) << "cannot get metadata from remote registry: " << e.what();
3964+ logger_() << "cannot get metadata from remote registry: " << e.what();
3965 }
3966 }
3967
3968@@ -182,7 +182,7 @@
3969 }
3970 catch (std::exception const& e)
3971 {
3972- BOOST_LOG(logger_) << "cannot get scopes list from remote registry: " << e.what();
3973+ logger_() << "cannot get scopes list from remote registry: " << e.what();
3974 }
3975 }
3976
3977@@ -377,8 +377,7 @@
3978 it->second->update_state(ScopeProcess::ProcessState::Stopping);
3979 break;
3980 default:
3981- BOOST_LOG(logger_)
3982- << "RegistryObject::on_state_received(): unknown state received from scope: " << scope_id;
3983+ logger_() << "RegistryObject::on_state_received(): unknown state received from scope: " << scope_id;
3984 }
3985 }
3986 // simply ignore states from scopes the registry does not know about
3987@@ -463,7 +462,7 @@
3988
3989 RegistryObject::ScopeProcess::ScopeProcess(ScopeExecData exec_data,
3990 std::weak_ptr<MWPublisher> const& publisher,
3991- boost::log::sources::severity_channel_logger_mt<>& logger)
3992+ unity::scopes::internal::Logger& logger)
3993 : exec_data_(exec_data)
3994 , reg_publisher_(publisher)
3995 , manually_started_(false)
3996@@ -479,7 +478,7 @@
3997 }
3998 catch(std::exception const& e)
3999 {
4000- BOOST_LOG(logger_) << "RegistryObject::ScopeProcess::~ScopeProcess(): " << e.what();
4001+ logger_() << "RegistryObject::ScopeProcess::~ScopeProcess(): " << e.what();
4002 }
4003 }
4004
4005@@ -518,16 +517,15 @@
4006 {
4007 if (!wait_for_state(lock, ScopeProcess::Stopped))
4008 {
4009- BOOST_LOG(logger_)
4010- << "RegistryObject::ScopeProcess::exec(): Force killing process. Scope: \""
4011- << exec_data_.scope_id << "\" did not stop after " << exec_data_.timeout_ms << " ms.";
4012+ logger_() << "RegistryObject::ScopeProcess::exec(): Force killing process. Scope: \""
4013+ << exec_data_.scope_id << "\" did not stop after " << exec_data_.timeout_ms << " ms.";
4014 try
4015 {
4016 kill(lock);
4017 }
4018 catch(std::exception const& e)
4019 {
4020- BOOST_LOG(logger_) << "RegistryObject::ScopeProcess::exec(): kill() failed: " << e.what();
4021+ logger_() << "RegistryObject::ScopeProcess::exec(): kill() failed: " << e.what();
4022 }
4023 }
4024 }
4025@@ -599,15 +597,15 @@
4026 }
4027 catch(std::exception const& e)
4028 {
4029- BOOST_LOG(logger_) << "RegistryObject::ScopeProcess::exec(): kill() failed: " << e.what();
4030+ logger_() << "RegistryObject::ScopeProcess::exec(): kill() failed: " << e.what();
4031 }
4032 throw unity::ResourceException("RegistryObject::ScopeProcess::exec(): exec aborted. Scope: \""
4033 + exec_data_.scope_id + "\" took longer than "
4034 + std::to_string(exec_data_.timeout_ms) + " ms to start.");
4035 }
4036
4037- BOOST_LOG_SEV(logger_, Logger::Info)
4038- << "RegistryObject::ScopeProcess::exec(): Process for scope: \"" << exec_data_.scope_id << "\" started";
4039+ logger_(LoggerSeverity::Info) << "RegistryObject::ScopeProcess::exec(): Process for scope: \""
4040+ << exec_data_.scope_id << "\" started";
4041
4042 // 4. add the scope process to the death observer
4043 death_observer.add(process_);
4044@@ -626,9 +624,8 @@
4045 // check if this is the process reported to have died
4046 if (pid == process_.pid())
4047 {
4048- BOOST_LOG_SEV(logger_, Logger::Info)
4049- << "RegistryObject::ScopeProcess::on_process_death(): Process for scope: \"" << exec_data_.scope_id
4050- << "\" exited";
4051+ logger_(LoggerSeverity::Info) << "RegistryObject::ScopeProcess::on_process_death(): Process for scope: \""
4052+ << exec_data_.scope_id << "\" exited";
4053 clear_handle_unlocked();
4054 return true;
4055 }
4056@@ -659,9 +656,8 @@
4057
4058 if (state_ != Starting)
4059 {
4060- BOOST_LOG_SEV(logger_, Logger::Info)
4061- << "RegistryObject::ScopeProcess: Process for scope: \"" << exec_data_.scope_id
4062- << "\" started manually";
4063+ logger_(LoggerSeverity::Info) << "RegistryObject::ScopeProcess: Process for scope: \""
4064+ << exec_data_.scope_id << "\" started manually";
4065
4066 manually_started_ = true;
4067 }
4068@@ -676,9 +672,8 @@
4069
4070 if (state_ != Stopping)
4071 {
4072- BOOST_LOG(logger_)
4073- << "RegistryObject::ScopeProcess: Scope: \"" << exec_data_.scope_id
4074- << "\" closed unexpectedly. Either the process crashed or was killed forcefully.";
4075+ logger_() << "RegistryObject::ScopeProcess: Scope: \"" << exec_data_.scope_id
4076+ << "\" closed unexpectedly. Either the process crashed or was killed forcefully.";
4077 }
4078 }
4079 else if (new_state == Stopping && manually_started_)
4080@@ -689,9 +684,8 @@
4081 reg_publisher->send_message("stopped", exec_data_.scope_id);
4082 }
4083
4084- BOOST_LOG(logger_)
4085- << "RegistryObject::ScopeProcess: Manually started process for scope: \""
4086- << exec_data_.scope_id << "\" exited";
4087+ logger_() << "RegistryObject::ScopeProcess: Manually started process for scope: \""
4088+ << exec_data_.scope_id << "\" exited";
4089
4090 new_state = Stopped;
4091 manually_started_ = false;
4092@@ -731,10 +725,9 @@
4093 {
4094 std::error_code ec;
4095
4096- BOOST_LOG(logger_)
4097- << "RegistryObject::ScopeProcess::kill(): Scope: \"" << exec_data_.scope_id
4098- << "\" took longer than " << exec_data_.timeout_ms << " ms to exit gracefully. "
4099- << "Killing the process instead.";
4100+ logger_() << "RegistryObject::ScopeProcess::kill(): Scope: \"" << exec_data_.scope_id
4101+ << "\" took longer than " << exec_data_.timeout_ms << " ms to exit gracefully. "
4102+ << "Killing the process instead.";
4103
4104 // scope is taking too long to close, send kill signal
4105 process_.send_signal(core::posix::Signal::sig_kill, ec);
4106@@ -745,8 +738,7 @@
4107 }
4108 catch (std::exception const&)
4109 {
4110- BOOST_LOG(logger_)
4111- << "RegistryObject::ScopeProcess::kill(): Failed to kill scope: \"" << exec_data_.scope_id << "\"";
4112+ logger_() << "RegistryObject::ScopeProcess::kill(): Failed to kill scope: \"" << exec_data_.scope_id << "\"";
4113
4114 // clear the process handle
4115 // even on error, the previous handle will be unrecoverable at this point
4116@@ -821,10 +813,9 @@
4117 started_message += " string:" + exec_data_.scope_id + " uint64:" + std::to_string(process_.pid());
4118 if (safe_system_call(started_message) != 0)
4119 {
4120- BOOST_LOG(logger_)
4121- << "RegistryObject::ScopeProcess::publish_state_change(): "
4122- "Failed to execute SDK DBus ScopeLoaded callback "
4123- "(Scope ID: " << exec_data_.scope_id << ")";
4124+ logger_() << "RegistryObject::ScopeProcess::publish_state_change(): "
4125+ "Failed to execute SDK DBus ScopeLoaded callback "
4126+ "(Scope ID: " << exec_data_.scope_id << ")";
4127 }
4128 }
4129 }
4130@@ -842,10 +833,9 @@
4131 stopped_message += " string:" + exec_data_.scope_id;
4132 if (safe_system_call(stopped_message) != 0)
4133 {
4134- BOOST_LOG(logger_)
4135- << "RegistryObject::ScopeProcess::publish_state_change(): "
4136- "Failed to execute SDK DBus ScopeStopped callback "
4137- "(Scope ID: " << exec_data_.scope_id << ")";
4138+ logger_() << "RegistryObject::ScopeProcess::publish_state_change(): "
4139+ "Failed to execute SDK DBus ScopeStopped callback "
4140+ "(Scope ID: " << exec_data_.scope_id << ")";
4141 }
4142 }
4143 }
4144
4145=== modified file 'src/scopes/internal/ReplyImpl.cpp'
4146--- src/scopes/internal/ReplyImpl.cpp 2015-11-25 08:55:19 +0000
4147+++ src/scopes/internal/ReplyImpl.cpp 2016-03-15 09:18:55 +0000
4148@@ -121,7 +121,7 @@
4149 {
4150 error_message = "unknown exception";
4151 }
4152- BOOST_LOG(mw_proxy_->mw_base()->runtime()->logger()) << "ReplyImpl::error(): " << error_message;
4153+ mw_proxy_->mw_base()->runtime()->logger()() << "ReplyImpl::error(): " << error_message;
4154
4155 try
4156 {
4157@@ -129,8 +129,7 @@
4158 }
4159 catch (std::exception const&)
4160 {
4161- BOOST_LOG(mw_proxy_->mw_base()->runtime()->logger())
4162- << "ReplyImpl::error(): exception from finished(): " << error_message;
4163+ mw_proxy_->mw_base()->runtime()->logger()() << "ReplyImpl::error(): exception from finished(): " << error_message;
4164 }
4165 }
4166
4167@@ -147,8 +146,7 @@
4168 }
4169 catch (std::exception const& e)
4170 {
4171- BOOST_LOG(mw_proxy_->mw_base()->runtime()->logger())
4172- << "ReplyImpl::error(): exception from info(): " << e.what();
4173+ mw_proxy_->mw_base()->runtime()->logger()() << "ReplyImpl::error(): exception from info(): " << e.what();
4174 }
4175 }
4176
4177
4178=== modified file 'src/scopes/internal/ReplyObject.cpp'
4179--- src/scopes/internal/ReplyObject.cpp 2015-06-09 07:27:24 +0000
4180+++ src/scopes/internal/ReplyObject.cpp 2016-03-15 09:18:55 +0000
4181@@ -135,7 +135,7 @@
4182 // Safe to call finished now if something went wrong or cardinality was exceeded.
4183 if (!error.empty())
4184 {
4185- BOOST_LOG(runtime_->logger()) << "ReplyObject::push(): " << error;
4186+ runtime_->logger()() << "ReplyObject::push(): " << error;
4187 finished(CompletionDetails(CompletionDetails::Error, error));
4188 }
4189 else if (stop)
4190@@ -183,11 +183,11 @@
4191 }
4192 catch (std::exception const& e)
4193 {
4194- BOOST_LOG(runtime_->logger()) << "ReplyObject::finished(): " << e.what();
4195+ runtime_->logger()() << "ReplyObject::finished(): " << e.what();
4196 }
4197 catch (...)
4198 {
4199- BOOST_LOG(runtime_->logger()) << "ReplyObject::finished(): unknown exception";
4200+ runtime_->logger()() << "ReplyObject::finished(): unknown exception";
4201 }
4202
4203 // Disconnect self from middleware, if this hasn't happened yet.
4204@@ -219,11 +219,11 @@
4205 }
4206 catch (std::exception const& e)
4207 {
4208- BOOST_LOG(runtime_->logger()) << "ReplyObject::info(): " << e.what();
4209+ runtime_->logger()() << "ReplyObject::info(): " << e.what();
4210 }
4211 catch (...)
4212 {
4213- BOOST_LOG(runtime_->logger()) << "ReplyObject::info(): unknown exception";
4214+ runtime_->logger()() << "ReplyObject::info(): unknown exception";
4215 }
4216 }
4217
4218
4219=== modified file 'src/scopes/internal/ResultReplyObject.cpp'
4220--- src/scopes/internal/ResultReplyObject.cpp 2015-06-09 07:27:24 +0000
4221+++ src/scopes/internal/ResultReplyObject.cpp 2016-03-15 09:18:55 +0000
4222@@ -24,6 +24,7 @@
4223 #include <unity/scopes/internal/CategorisedResultImpl.h>
4224 #include <unity/scopes/internal/DepartmentImpl.h>
4225 #include <unity/scopes/FilterBase.h>
4226+#include <unity/scopes/internal/FilterGroupImpl.h>
4227 #include <unity/scopes/internal/FilterBaseImpl.h>
4228 #include <unity/scopes/internal/FilterStateImpl.h>
4229 #include <unity/UnityExceptions.h>
4230@@ -65,7 +66,14 @@
4231 auto it = data.find("filters");
4232 if (it != data.end())
4233 {
4234- Filters const filters = FilterBaseImpl::deserialize_filters(it->second.get_array());
4235+ auto itgr = data.find("filter_groups");
4236+ std::map<std::string, FilterGroup::SCPtr> groups;
4237+ if (itgr != data.end())
4238+ {
4239+ groups = FilterGroupImpl::deserialize_filter_groups(itgr->second.get_array());
4240+ }
4241+
4242+ Filters const filters = FilterBaseImpl::deserialize_filters(it->second.get_array(), groups);
4243 it = data.find("filter_state");
4244 if (it != data.end())
4245 {
4246
4247=== modified file 'src/scopes/internal/RuntimeConfig.cpp'
4248--- src/scopes/internal/RuntimeConfig.cpp 2015-12-16 06:55:08 +0000
4249+++ src/scopes/internal/RuntimeConfig.cpp 2016-03-15 09:18:55 +0000
4250@@ -53,9 +53,6 @@
4251 const string cache_dir_key = "CacheDir";
4252 const string app_dir_key = "AppDir";
4253 const string config_dir_key = "ConfigDir";
4254-const string log_dir_key = "LogDir";
4255-const string max_log_file_size_key = "Log.MaxFileSize";
4256-const string max_log_dir_size_key = "Log.MaxDirSize";
4257 const string trace_channels_key = "Log.TraceChannels";
4258
4259 } // namespace
4260@@ -73,8 +70,6 @@
4261 default_middleware_configfile_ = DFLT_ZMQ_MIDDLEWARE_INI;
4262 reap_expiry_ = DFLT_REAP_EXPIRY;
4263 reap_interval_ = DFLT_REAP_INTERVAL;
4264- max_log_file_size_ = DFLT_MAX_LOG_FILE_SIZE;
4265- max_log_dir_size_ = DFLT_MAX_LOG_DIR_SIZE;
4266 cache_directory_ = default_cache_directory();
4267 app_directory_ = default_app_directory();
4268 config_directory_ = default_config_directory();
4269@@ -142,29 +137,6 @@
4270 }
4271 }
4272
4273- log_directory_ = get_optional_string(runtime_config_group, log_dir_key);
4274-
4275- // Check if we have an override for the log directory.
4276- char const* logdir = getenv("UNITY_SCOPES_LOGDIR");
4277- if (logdir)
4278- {
4279- log_directory_ = logdir;
4280- }
4281-
4282- max_log_file_size_ = get_optional_int(runtime_config_group, max_log_file_size_key, DFLT_MAX_LOG_FILE_SIZE);
4283- if (max_log_file_size_ < 1024)
4284- {
4285- throw_ex("Illegal value (" + to_string(max_log_file_size_) + ") for " + max_log_file_size_key
4286- + ": value must be > 1024");
4287- }
4288-
4289- max_log_dir_size_ = get_optional_int(runtime_config_group, max_log_dir_size_key, DFLT_MAX_LOG_DIR_SIZE);
4290- if (max_log_dir_size_ <= max_log_file_size_)
4291- {
4292- throw_ex("Illegal value (" + to_string(max_log_dir_size_) + ") for " + max_log_dir_size_key
4293- + ": value must be > " + max_log_file_size_key + " (" + to_string(max_log_file_size_) + ")");
4294- }
4295-
4296 try
4297 {
4298 trace_channels_ = parser()->get_string_array(runtime_config_group, trace_channels_key);
4299@@ -198,9 +170,6 @@
4300 cache_dir_key,
4301 app_dir_key,
4302 config_dir_key,
4303- log_dir_key,
4304- max_log_file_size_key,
4305- max_log_dir_size_key,
4306 trace_channels_key
4307 }
4308 }
4309@@ -267,21 +236,6 @@
4310 return config_directory_;
4311 }
4312
4313-string RuntimeConfig::log_directory() const
4314-{
4315- return log_directory_;
4316-}
4317-
4318-int RuntimeConfig::max_log_file_size() const
4319-{
4320- return max_log_file_size_;
4321-}
4322-
4323-int RuntimeConfig::max_log_dir_size() const
4324-{
4325- return max_log_dir_size_;
4326-}
4327-
4328 vector<string> RuntimeConfig::trace_channels() const
4329 {
4330 return trace_channels_;
4331@@ -317,19 +271,6 @@
4332 return string(home) + "/" + DFLT_HOME_CONFIG_SUBDIR;
4333 }
4334
4335-string RuntimeConfig::default_log_directory()
4336-{
4337- char const* home = getenv("HOME");
4338- if (!home || *home == '\0')
4339- {
4340- throw ResourceException("RuntimeConfig::default_log_directory(): $HOME not set");
4341- }
4342- string dir = string(home) + "/" + DFLT_HOME_LOG_SUBDIR;
4343- make_directories(dir, 0700);
4344-
4345- return dir;
4346-}
4347-
4348 } // namespace internal
4349
4350 } // namespace scopes
4351
4352=== modified file 'src/scopes/internal/RuntimeImpl.cpp'
4353--- src/scopes/internal/RuntimeImpl.cpp 2015-12-18 09:21:53 +0000
4354+++ src/scopes/internal/RuntimeImpl.cpp 2016-03-15 09:18:55 +0000
4355@@ -81,23 +81,16 @@
4356 RuntimeConfig config(configfile);
4357
4358 // Configure trace channels.
4359- try
4360- {
4361- logger_->enable_channels(config.trace_channels());
4362- }
4363- catch (...)
4364- {
4365- throw InvalidArgumentException("Runtime(): invalid trace channel name(s)");
4366- }
4367-
4368- // Now that we have the config, change the logger to log to a file.
4369- // If log_dir is set to the empty string, continue logging to std::clog.
4370- log_dir_ = config.log_directory();
4371- if (!log_dir_.empty())
4372- {
4373- logger_->set_log_file(find_log_dir(log_file_basename) + "/" + log_file_basename,
4374- config.max_log_file_size(),
4375- config.max_log_dir_size());
4376+ for (auto const& c : config.trace_channels())
4377+ {
4378+ try
4379+ {
4380+ logger_->set_channel(c, true);
4381+ }
4382+ catch (...)
4383+ {
4384+ throw InvalidArgumentException("Runtime(): invalid trace channel name");
4385+ }
4386 }
4387
4388 string default_middleware = config.default_middleware();
4389@@ -119,7 +112,7 @@
4390
4391 if (registry_configfile_.empty() || registry_identity_.empty())
4392 {
4393- BOOST_LOG_SEV(logger(), Logger::Warning) << "no registry configured";
4394+ logger()(LoggerSeverity::Warning) << "no registry configured";
4395 registry_identity_ = "";
4396 }
4397 else
4398@@ -140,7 +133,7 @@
4399 string msg = "Cannot instantiate run time for " + (scope_id.empty() ? "client" : scope_id) +
4400 ", config file: " + configfile;
4401 ConfigException ex(msg);
4402- BOOST_LOG(logger()) << ex.what();
4403+ logger()() << ex.what();
4404 throw ex;
4405 }
4406 }
4407@@ -153,11 +146,11 @@
4408 }
4409 catch (std::exception const& e) // LCOV_EXCL_LINE
4410 {
4411- BOOST_LOG(logger()) << "~RuntimeImpl(): " << e.what();
4412+ logger()() << "~RuntimeImpl(): " << e.what();
4413 }
4414 catch (...) // LCOV_EXCL_LINE
4415 {
4416- BOOST_LOG(logger()) << "~RuntimeImpl(): unknown exception";
4417+ logger()() << "~RuntimeImpl(): unknown exception";
4418 }
4419 }
4420
4421@@ -311,16 +304,11 @@
4422 return future_queue_; // Immutable
4423 }
4424
4425-boost::log::sources::severity_channel_logger_mt<>& RuntimeImpl::logger() const
4426+internal::Logger& RuntimeImpl::logger() const
4427 {
4428 return *logger_;
4429 }
4430
4431-boost::log::sources::severity_channel_logger_mt<>& RuntimeImpl::logger(Logger::Channel channel) const
4432-{
4433- return (*logger_)(channel);
4434-}
4435-
4436 namespace
4437 {
4438
4439
4440=== modified file 'src/scopes/internal/ScopeObject.cpp'
4441--- src/scopes/internal/ScopeObject.cpp 2015-06-01 13:33:27 +0000
4442+++ src/scopes/internal/ScopeObject.cpp 2016-03-15 09:18:55 +0000
4443@@ -84,7 +84,7 @@
4444 if (!query_base)
4445 {
4446 string msg = "Scope \"" + mw_base->runtime()->scope_id() + "\" returned nullptr from " + method + "()";
4447- BOOST_LOG(mw_base->runtime()->logger()) << msg;
4448+ mw_base->runtime()->logger()() << msg;
4449 throw ResourceException(msg);
4450 }
4451 query_base->p->set_settings_db(scope_base_->p->settings_db());
4452@@ -92,7 +92,7 @@
4453 catch (...)
4454 {
4455 string msg = "Scope \"" + mw_base->runtime()->scope_id() + "\" threw an exception from " + method + "()";
4456- BOOST_LOG(mw_base->runtime()->logger()) << msg;
4457+ mw_base->runtime()->logger()() << msg;
4458 throw ResourceException(msg);
4459 }
4460
4461@@ -130,7 +130,7 @@
4462 catch (...)
4463 {
4464 }
4465- BOOST_LOG(mw_base->runtime()->logger()) << "ScopeObject::query(): " << e.what();
4466+ mw_base->runtime()->logger()() << "ScopeObject::query(): " << e.what();
4467 throw;
4468 }
4469 catch (...)
4470@@ -142,7 +142,7 @@
4471 catch (...)
4472 {
4473 }
4474- BOOST_LOG(mw_base->runtime()->logger()) << "ScopeObject::query(): unknown exception";
4475+ mw_base->runtime()->logger()() << "ScopeObject::query(): unknown exception";
4476 throw;
4477 }
4478 return ctrl_proxy;
4479
4480=== modified file 'src/scopes/internal/SearchQueryBaseImpl.cpp'
4481--- src/scopes/internal/SearchQueryBaseImpl.cpp 2015-05-29 15:06:06 +0000
4482+++ src/scopes/internal/SearchQueryBaseImpl.cpp 2016-03-15 09:18:55 +0000
4483@@ -210,8 +210,7 @@
4484 // scope_impl can be nullptr if we use a mock scope: TypedScopeFixture<testing::Scope>
4485 if (scope_impl)
4486 {
4487- auto logger = scope_impl->runtime()->logger();
4488- BOOST_LOG_SEV(logger, Logger::Warning)
4489+ scope_impl->runtime()->logger()(LoggerSeverity::Warning)
4490 << "query loop for query \"" << canned_query_.query_string()
4491 << "\", client: " << get<0>(tuple)
4492 << ", aggregator: " << get<1>(tuple)
4493
4494=== modified file 'src/scopes/internal/SearchReplyImpl.cpp'
4495--- src/scopes/internal/SearchReplyImpl.cpp 2015-11-25 08:55:19 +0000
4496+++ src/scopes/internal/SearchReplyImpl.cpp 2016-03-15 09:18:55 +0000
4497@@ -24,14 +24,19 @@
4498 #include <unity/scopes/internal/DepartmentImpl.h>
4499 #include <unity/scopes/internal/FilterBaseImpl.h>
4500 #include <unity/scopes/internal/FilterStateImpl.h>
4501+#include <unity/scopes/internal/FilterGroupImpl.h>
4502 #include <unity/scopes/internal/MWReply.h>
4503 #include <unity/scopes/internal/QueryObjectBase.h>
4504 #include <unity/scopes/internal/RuntimeImpl.h>
4505 #include <unity/scopes/ScopeExceptions.h>
4506 #include <unity/UnityExceptions.h>
4507 #include <unity/util/FileIO.h>
4508+#include <unity/util/ResourcePtr.h>
4509+
4510+#include <cassert>
4511
4512 #include <stdlib.h>
4513+#include <unistd.h>
4514
4515 using namespace std;
4516
4517@@ -185,6 +190,11 @@
4518 }
4519
4520 VariantMap var;
4521+ auto filter_groups = internal::FilterGroupImpl::serialize_filter_groups(filters);
4522+ if (filter_groups.size())
4523+ {
4524+ var["filter_groups"] = filter_groups;
4525+ }
4526 var["filters"] = internal::FilterBaseImpl::serialize_filters(filters);
4527 var["filter_state"] = filter_state.serialize();
4528 return ReplyImpl::push(var);
4529@@ -260,8 +270,17 @@
4530 VariantMap vm;
4531 vm["departments"] = move(departments);
4532 vm["categories"] = move(categories);
4533+
4534+ // serialize filter groups if present
4535+ auto filter_groups = internal::FilterGroupImpl::serialize_filter_groups(cached_filters_);
4536+ if (filter_groups.size())
4537+ {
4538+ vm["filter_groups"] = move(filter_groups);
4539+ }
4540+
4541 vm["filters"] = move(filters);
4542 vm["filter_state"] = move(filter_state);
4543+
4544 vm["results"] = move(results);
4545 string const json = Variant(move(vm)).serialize_json();
4546
4547@@ -285,15 +304,13 @@
4548 catch (std::exception const& e)
4549 {
4550 ::unlink(tmp_path.c_str());
4551- BOOST_LOG(mw_proxy_->mw_base()->runtime()->logger())
4552- << "SearchReply::write_cached_results(): " << e.what();
4553+ mw_proxy_->mw_base()->runtime()->logger()() << "SearchReply::write_cached_results(): " << e.what();
4554 }
4555 // LCOV_EXCL_START
4556 catch (...)
4557 {
4558 ::unlink(tmp_path.c_str());
4559- BOOST_LOG(mw_proxy_->mw_base()->runtime()->logger())
4560- << "SearchReply::write_cached_results(): unknown exception";
4561+ mw_proxy_->mw_base()->runtime()->logger()() << "SearchReply::write_cached_results(): unknown exception";
4562 }
4563 // LCOV_EXCL_STOP
4564 }
4565@@ -383,7 +400,14 @@
4566 register_category(cp);
4567 }
4568
4569- auto filters = FilterBaseImpl::deserialize_filters(move(filter_array));
4570+ std::map<std::string, FilterGroup::SCPtr> groups;
4571+ it = vm.find("filter_groups");
4572+ if (it != vm.end())
4573+ {
4574+ groups = FilterGroupImpl::deserialize_filter_groups(it->second.get_array());
4575+ }
4576+
4577+ auto filters = FilterBaseImpl::deserialize_filters(move(filter_array), groups);
4578 auto filter_state = FilterStateImpl::deserialize(move(filter_state_dict));
4579 push(filters, filter_state);
4580
4581@@ -396,13 +420,13 @@
4582 }
4583 catch (std::exception const& e)
4584 {
4585- BOOST_LOG(mw_proxy_->mw_base()->runtime()->logger())
4586+ mw_proxy_->mw_base()->runtime()->logger()()
4587 << "SearchReply::push_surfacing_results_from_cache() (file = " + cache_path + "): " << e.what();
4588 }
4589 // LCOV_EXCL_START
4590 catch (...)
4591 {
4592- BOOST_LOG(mw_proxy_->mw_base()->runtime()->logger())
4593+ mw_proxy_->mw_base()->runtime()->logger()()
4594 << "SearchReply::push_surfacing_results_from_cache() (file = " + cache_path + "): unknown exception";
4595 }
4596 // LCOV_EXCL_STOP
4597
4598=== modified file 'src/scopes/internal/ValueSliderFilterImpl.cpp'
4599--- src/scopes/internal/ValueSliderFilterImpl.cpp 2015-11-12 14:20:36 +0000
4600+++ src/scopes/internal/ValueSliderFilterImpl.cpp 2016-03-15 09:18:55 +0000
4601@@ -32,26 +32,21 @@
4602 namespace internal
4603 {
4604
4605-ValueSliderFilterImpl::ValueSliderFilterImpl(std::string const& id, std::string const& label, std::string const& label_template, double min, double max)
4606+ValueSliderFilterImpl::ValueSliderFilterImpl(std::string const& id, double min, double max, double default_value, ValueSliderLabels const& labels)
4607 : FilterBaseImpl(id),
4608- label_(label),
4609- label_template_(label_template),
4610- slider_type_(ValueSliderFilter::SliderType::LessThan),
4611 min_(min),
4612- max_(max)
4613+ max_(max),
4614+ default_val_(default_value),
4615+ labels_(new ValueSliderLabels(labels))
4616 {
4617- if (label.empty())
4618- {
4619- throw InvalidArgumentException("ValueSliderFilterImpl(): Invalid empty label string");
4620- }
4621-
4622- if (min < 0 || min >= max)
4623+ if (default_value < min || default_value > max)
4624 {
4625 std::stringstream err;
4626- err << "ValueSliderFilterImpl::ValueSliderFilterImpl(): invalid min or max value for filter '" << id << "', min is " << min << ", max is " << max;
4627- throw LogicException(err.str());
4628+ err << "ValueSliderFilterImpl::ValueSliderFilterImpl(): invalid default value for filter '" << id << "', " << default_value << " not in " << min << "-"
4629+ << max << " range";
4630+ throw InvalidArgumentException(err.str());
4631 }
4632- default_val_ = max;
4633+ labels_->p->validate(min_, max_);
4634 }
4635
4636 ValueSliderFilterImpl::ValueSliderFilterImpl(VariantMap const& var)
4637@@ -73,16 +68,6 @@
4638 default_val_ = val;
4639 }
4640
4641-void ValueSliderFilterImpl::set_slider_type(ValueSliderFilter::SliderType tp)
4642-{
4643- slider_type_ = tp;
4644-}
4645-
4646-ValueSliderFilter::SliderType ValueSliderFilterImpl::slider_type() const
4647-{
4648- return slider_type_;
4649-}
4650-
4651 double ValueSliderFilterImpl::default_value() const
4652 {
4653 return default_val_;
4654@@ -98,14 +83,11 @@
4655 return max_;
4656 }
4657
4658-std::string ValueSliderFilterImpl::label() const
4659-{
4660- return label_;
4661-}
4662-
4663-std::string ValueSliderFilterImpl::value_label_template() const
4664-{
4665- return label_template_;
4666+ValueSliderLabels const& ValueSliderFilterImpl::labels() const
4667+{
4668+ // labels_ pointer is guaranteed to be initialized either by the regular ctor or when deserialized from a variant
4669+ assert(labels_);
4670+ return *labels_;
4671 }
4672
4673 bool ValueSliderFilterImpl::has_value(FilterState const& filter_state) const
4674@@ -119,7 +101,7 @@
4675 {
4676 try
4677 {
4678- double val = FilterBaseImpl::get(filter_state, id()).get_double(); // this can throw if of different type
4679+ auto val = FilterBaseImpl::get(filter_state, id()).get_double(); // this can throw if of different type
4680 check_range(val);
4681 return val;
4682 }
4683@@ -129,7 +111,7 @@
4684 // via a canned query from another scope, we shouldn't break this scope on it.
4685 }
4686 }
4687- throw NotFoundException("ValueSliderFilterImpl::get_value(): value is not set for filter", id());
4688+ return default_val_;
4689 }
4690
4691 void ValueSliderFilterImpl::update_state(FilterState& filter_state, double value) const
4692@@ -154,28 +136,23 @@
4693
4694 void ValueSliderFilterImpl::serialize(VariantMap& var) const
4695 {
4696- var["label"] = label_;
4697- var["label_template"] = label_template_;
4698 var["min"] = Variant(min_);
4699 var["max"] = Variant(max_);
4700 var["default"] = Variant(default_val_);
4701- var["slider_type"] = static_cast<int>(slider_type_);
4702+ var["labels"] = Variant(labels_->serialize());
4703 }
4704
4705 void ValueSliderFilterImpl::deserialize(VariantMap const& var)
4706 {
4707- auto it = find_or_throw("ValueSliderFilterImpl::deserialize()", var, "label");
4708- label_ = it->second.get_string();
4709- it = find_or_throw("ValueSliderFilterImpl::deserialize()", var, "label_template");
4710- label_template_ = it->second.get_string();
4711- it = find_or_throw("ValueSliderFilterImpl::deserialize()", var, "min");
4712+ auto it = find_or_throw("ValueSliderFilterImpl::deserialize()", var, "min");
4713 min_ = it->second.get_double();
4714 it = find_or_throw("ValueSliderFilterImpl::deserialize()", var, "max");
4715 max_ = it->second.get_double();
4716 it = find_or_throw("ValueSliderFilterImpl::deserialize()", var, "default");
4717 default_val_ = it->second.get_double();
4718- it = find_or_throw("ValueSliderFilterImpl::deserialize()", var, "slider_type");
4719- slider_type_ = static_cast<ValueSliderFilter::SliderType>(it->second.get_int());
4720+ it = find_or_throw("ValueSliderFilterImpl::deserialize()", var, "labels");
4721+ labels_.reset(new ValueSliderLabels(it->second.get_dict()));
4722+ labels_->p->validate(min_, max_);
4723 }
4724
4725 std::string ValueSliderFilterImpl::filter_type() const
4726@@ -189,7 +166,7 @@
4727 {
4728 std::stringstream err;
4729 err << "ValueSliderFilterImpl::check_range(): value " << val << " outside of allowed range (" << min_ << ", " << max_ << ")";
4730- throw LogicException(err.str());
4731+ throw InvalidArgumentException(err.str());
4732 }
4733 }
4734
4735
4736=== added file 'src/scopes/internal/ValueSliderLabelsImpl.cpp'
4737--- src/scopes/internal/ValueSliderLabelsImpl.cpp 1970-01-01 00:00:00 +0000
4738+++ src/scopes/internal/ValueSliderLabelsImpl.cpp 2016-03-15 09:18:55 +0000
4739@@ -0,0 +1,158 @@
4740+/*
4741+ * Copyright (C) 2015 Canonical Ltd
4742+ *
4743+ * This program is free software: you can redistribute it and/or modify
4744+ * it under the terms of the GNU Lesser General Public License version 3 as
4745+ * published by the Free Software Foundation.
4746+ *
4747+ * This program is distributed in the hope that it will be useful,
4748+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4749+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4750+ * GNU Lesser General Public License for more details.
4751+ *
4752+ * You should have received a copy of the GNU Lesser General Public License
4753+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4754+ *
4755+ * Authored by: Pawel Stolowski <pawel.stolowski@canonical.com>
4756+ */
4757+
4758+#include <unity/scopes/internal/ValueSliderLabelsImpl.h>
4759+#include <unity/scopes/internal/Utils.h>
4760+#include <unity/UnityExceptions.h>
4761+#include <unordered_set>
4762+
4763+namespace unity
4764+{
4765+
4766+namespace scopes
4767+{
4768+
4769+namespace internal
4770+{
4771+
4772+ValueSliderLabelsImpl::ValueSliderLabelsImpl(std::string const& min_label, std::string const& max_label)
4773+ : min_label_(min_label),
4774+ max_label_(max_label)
4775+{
4776+}
4777+
4778+ValueSliderLabelsImpl::ValueSliderLabelsImpl(std::string const& min_label, std::string const& max_label, std::vector<std::pair<double, std::string>> const& extra_labels)
4779+ : min_label_(min_label),
4780+ max_label_(max_label),
4781+ extra_labels_(extra_labels)
4782+{
4783+}
4784+
4785+ValueSliderLabelsImpl::ValueSliderLabelsImpl(VariantMap const& var)
4786+{
4787+ deserialize(var);
4788+}
4789+
4790+std::string ValueSliderLabelsImpl::min_label() const
4791+{
4792+ return min_label_;
4793+}
4794+
4795+std::string ValueSliderLabelsImpl::max_label() const
4796+{
4797+ return max_label_;
4798+}
4799+
4800+std::vector<std::pair<double, std::string>> ValueSliderLabelsImpl::extra_labels() const
4801+{
4802+ return extra_labels_;
4803+}
4804+
4805+void ValueSliderLabelsImpl::validate(double min, double max) const
4806+{
4807+ if (min >= max)
4808+ {
4809+ std::stringstream err;
4810+ err << "ValueSliderLabelsImpl::validate(): invalid range " << min << ", " << max;
4811+ throw InvalidArgumentException(err.str());
4812+ }
4813+
4814+ double last_value = min;
4815+ std::unordered_set<std::string> label_lut;
4816+
4817+ // check that values of extra labels grow, i.e. v1 < v2 < v3 ... and lables are unique and not empty
4818+ for (auto const &p: extra_labels_)
4819+ {
4820+ if (p.first <= last_value)
4821+ {
4822+ std::stringstream err;
4823+ err << "ValueSliderLabelsImpl::validate(): value " << p.first << " for extra label '" << p.second << "' must be greater than previous value";
4824+ throw InvalidArgumentException(err.str());
4825+ }
4826+ if (p.second == "")
4827+ {
4828+ std::stringstream err;
4829+ err << "ValueSliderLabelsImpl::validate(): extra label for value " << p.first << " cannot be empty";
4830+ throw InvalidArgumentException(err.str());
4831+ }
4832+ if (p.second == min_label_ || p.second == max_label_)
4833+ {
4834+ std::stringstream err;
4835+ err << "ValueSliderLabelsImpl::validate(): extra label for value " << p.first << " must not be equal to min or max labels";
4836+ throw InvalidArgumentException(err.str());
4837+ }
4838+ if (label_lut.find(p.second) != label_lut.end())
4839+ {
4840+ std::stringstream err;
4841+ err << "ValueSliderLabelsImpl::validate(): multiple definitions of label '" << p.second << "'";
4842+ throw InvalidArgumentException(err.str());
4843+ }
4844+ label_lut.insert(p.second);
4845+ last_value = p.first;
4846+ }
4847+
4848+ if (max <= last_value)
4849+ {
4850+ std::stringstream err;
4851+ err << "ValueSliderLabelsImpl::validate(): the value of last extra label must not be greater than the maximum value " << max;
4852+ throw InvalidArgumentException(err.str());
4853+ }
4854+}
4855+
4856+VariantMap ValueSliderLabelsImpl::serialize() const
4857+{
4858+ VariantMap vm;
4859+ VariantArray va;
4860+ for (auto const& p: extra_labels_)
4861+ {
4862+ va.push_back(Variant(p.first));
4863+ va.push_back(Variant(p.second));
4864+ }
4865+ vm["extra_labels"] = Variant(va);
4866+ vm["min_label"] = Variant(min_label_);
4867+ vm["max_label"] = Variant(max_label_);
4868+ return vm;
4869+}
4870+
4871+void ValueSliderLabelsImpl::deserialize(VariantMap const& var)
4872+{
4873+ auto it = find_or_throw("ValueSliderLabels::deserialize()", var, "min_label");
4874+ min_label_ = it->second.get_string();
4875+ it = find_or_throw("ValueSliderLabels::deserialize()", var, "max_label");
4876+ max_label_ = it->second.get_string();
4877+ it = var.find("extra_labels");
4878+ if (it != var.end())
4879+ {
4880+ auto const va = it->second.get_array();
4881+ for (auto it = va.begin(); it != va.end();)
4882+ {
4883+ auto const value = (it++)->get_double();
4884+ if (it == va.end())
4885+ {
4886+ throw unity::InvalidArgumentException("ValueSliderLabels::deserialize(): invalid value-label array");
4887+ }
4888+ std::string const label = (it++)->get_string();
4889+ extra_labels_.push_back(std::make_pair<>(value, label));
4890+ }
4891+ }
4892+}
4893+}
4894+
4895+}
4896+
4897+}
4898
4899=== modified file 'src/scopes/internal/smartscopes/SSQueryObject.cpp'
4900--- src/scopes/internal/smartscopes/SSQueryObject.cpp 2015-01-09 07:10:07 +0000
4901+++ src/scopes/internal/smartscopes/SSQueryObject.cpp 2016-03-15 09:18:55 +0000
4902@@ -95,7 +95,7 @@
4903 std::lock_guard<std::mutex> lock(queries_mutex_);
4904
4905 query_it->second->q_pushable = false;
4906- BOOST_LOG(info.mw->runtime()->logger()) << "SSQueryObject::run(): " << e.what();
4907+ info.mw->runtime()->logger()() << "SSQueryObject::run(): " << e.what();
4908 reply->finished(CompletionDetails(CompletionDetails::Error, e.what())); // Oneway, can't block
4909 }
4910 catch (...)
4911@@ -103,7 +103,7 @@
4912 std::lock_guard<std::mutex> lock(queries_mutex_);
4913
4914 query_it->second->q_pushable = false;
4915- BOOST_LOG(info.mw->runtime()->logger()) << "SSQueryObject::run(): unknown exception";
4916+ info.mw->runtime()->logger()() << "SSQueryObject::run(): unknown exception";
4917 reply->finished(CompletionDetails(CompletionDetails::Error, "unknown exception")); // Oneway, can't block
4918 }
4919
4920
4921=== modified file 'src/scopes/internal/smartscopes/SSRegistryObject.cpp'
4922--- src/scopes/internal/smartscopes/SSRegistryObject.cpp 2015-11-26 05:48:01 +0000
4923+++ src/scopes/internal/smartscopes/SSRegistryObject.cpp 2016-03-15 09:18:55 +0000
4924@@ -82,7 +82,7 @@
4925 catch (std::exception const& e)
4926 {
4927
4928- BOOST_LOG(middleware_->runtime()->logger()) << "SSRegistryObject: get_remote_scopes() failed: " << e.what();
4929+ middleware_->runtime()->logger()() << "SSRegistryObject: get_remote_scopes() failed: " << e.what();
4930 }
4931
4932 refresh_thread_ = std::thread(&SSRegistryObject::refresh_thread, this);
4933@@ -95,8 +95,8 @@
4934 }
4935 catch (std::exception const& e)
4936 {
4937- BOOST_LOG(middleware_->runtime()->logger())
4938- << "SSRegistryObject(): failed to create registry publisher: " << e.what();
4939+ middleware_->runtime()->logger()() << "SSRegistryObject(): failed to create registry publisher: "
4940+ << e.what();
4941 }
4942 }
4943 }
4944@@ -209,8 +209,7 @@
4945 }
4946 catch (std::exception const& e)
4947 {
4948- BOOST_LOG(middleware_->runtime()->logger())
4949- << "SSRegistryObject: get_remote_scopes() failed: " << e.what();
4950+ middleware_->runtime()->logger()() << "SSRegistryObject: get_remote_scopes() failed: " << e.what();
4951 }
4952 }
4953 }
4954@@ -283,9 +282,9 @@
4955 }
4956 catch (ResourceException const& e)
4957 {
4958- BOOST_LOG(middleware_->runtime()->logger())
4959- << "SSRegistryObject: ignoring invalid settings JSON for scope \"" << scope.id << "\": "
4960- << e.what();
4961+ middleware_->runtime()->logger()()
4962+ << "SSRegistryObject: ignoring invalid settings JSON for scope \""
4963+ << scope.id << "\": " << e.what();
4964 }
4965 }
4966 else if (needs_location_data)
4967@@ -330,9 +329,8 @@
4968 }
4969 catch (ResourceException const& e)
4970 {
4971- BOOST_LOG(middleware_->runtime()->logger())
4972- << "SSRegistryObject: ignoring invalid settings JSON for scope \"" << scope.id << "\": "
4973- << e.what();
4974+ middleware_->runtime()->logger()() << "SSRegistryObject: ignoring invalid settings JSON for scope \""
4975+ << scope.id << "\": " << e.what();
4976 }
4977 }
4978
4979@@ -356,8 +354,8 @@
4980 }
4981 catch (std::exception const& e)
4982 {
4983- BOOST_LOG(middleware_->runtime()->logger())
4984- << "SSRegistryObject: skipping scope \"" << scope.id << "\": " << e.what();
4985+ middleware_->runtime()->logger()() << "SSRegistryObject: skipping scope \""
4986+ << scope.id << "\": " << e.what();
4987 }
4988 }
4989
4990
4991=== modified file 'src/scopes/internal/smartscopes/SSScopeObject.cpp'
4992--- src/scopes/internal/smartscopes/SSScopeObject.cpp 2015-05-29 12:02:54 +0000
4993+++ src/scopes/internal/smartscopes/SSScopeObject.cpp 2016-03-15 09:18:55 +0000
4994@@ -187,7 +187,7 @@
4995 catch (...)
4996 {
4997 }
4998- BOOST_LOG(info.mw->runtime()->logger()) << "SSScopeObject::query(): " << e.what();
4999+ info.mw->runtime()->logger()() << "SSScopeObject::query(): " << e.what();
5000 throw;
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches

to all changes: