Merge lp:~pete-woods/qtcreator-plugin-ubuntu/new-scope-template into lp:qtcreator-plugin-ubuntu
- new-scope-template
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Zoltan Balogh |
Approved revision: | 259 |
Merged at revision: | 260 |
Proposed branch: | lp:~pete-woods/qtcreator-plugin-ubuntu/new-scope-template |
Merge into: | lp:qtcreator-plugin-ubuntu |
Diff against target: |
1712 lines (+1234/-276) 32 files modified
share/qtcreator/templates/wizards/ubuntu/scope/CMakeLists.txt (+63/-17) share/qtcreator/templates/wizards/ubuntu/scope/cmake/FindGMock.cmake (+12/-0) share/qtcreator/templates/wizards/ubuntu/scope/data/CMakeLists.txt (+13/-8) share/qtcreator/templates/wizards/ubuntu/scope/data/displayName.ini (+9/-0) share/qtcreator/templates/wizards/ubuntu/scope/data/displayName.ini.in (+0/-8) share/qtcreator/templates/wizards/ubuntu/scope/include/api/client.h (+121/-0) share/qtcreator/templates/wizards/ubuntu/scope/include/api/config.h (+25/-0) share/qtcreator/templates/wizards/ubuntu/scope/include/scope/preview.h (+37/-0) share/qtcreator/templates/wizards/ubuntu/scope/include/scope/query.h (+36/-0) share/qtcreator/templates/wizards/ubuntu/scope/include/scope/scope.h (+53/-0) share/qtcreator/templates/wizards/ubuntu/scope/src/CMakeLists.txt (+50/-11) share/qtcreator/templates/wizards/ubuntu/scope/src/api/client.cpp (+157/-0) share/qtcreator/templates/wizards/ubuntu/scope/src/displayName-preview.cpp (+0/-49) share/qtcreator/templates/wizards/ubuntu/scope/src/displayName-preview.h (+0/-18) share/qtcreator/templates/wizards/ubuntu/scope/src/displayName-query.cpp (+0/-54) share/qtcreator/templates/wizards/ubuntu/scope/src/displayName-query.h (+0/-17) share/qtcreator/templates/wizards/ubuntu/scope/src/displayName-scope.cpp (+0/-49) share/qtcreator/templates/wizards/ubuntu/scope/src/displayName-scope.h (+0/-24) share/qtcreator/templates/wizards/ubuntu/scope/src/scope/preview.cpp (+60/-0) share/qtcreator/templates/wizards/ubuntu/scope/src/scope/query.cpp (+177/-0) share/qtcreator/templates/wizards/ubuntu/scope/src/scope/scope.cpp (+58/-0) share/qtcreator/templates/wizards/ubuntu/scope/test/CMakeLists.txt (+0/-2) share/qtcreator/templates/wizards/ubuntu/scope/test/simpletest.cpp (+0/-3) share/qtcreator/templates/wizards/ubuntu/scope/tests/CMakeLists.txt (+25/-0) share/qtcreator/templates/wizards/ubuntu/scope/tests/server/forecast/daily/London,uk.json (+1/-0) share/qtcreator/templates/wizards/ubuntu/scope/tests/server/forecast/daily/Manchester,uk.json (+1/-0) share/qtcreator/templates/wizards/ubuntu/scope/tests/server/server.py (+51/-0) share/qtcreator/templates/wizards/ubuntu/scope/tests/server/weather/London,uk.json (+1/-0) share/qtcreator/templates/wizards/ubuntu/scope/tests/server/weather/Manchester,uk.json (+1/-0) share/qtcreator/templates/wizards/ubuntu/scope/tests/unit/CMakeLists.txt (+24/-0) share/qtcreator/templates/wizards/ubuntu/scope/tests/unit/scope/test-scope.cpp (+225/-0) share/qtcreator/templates/wizards/ubuntu/scope/wizard.xml (+34/-16) |
To merge this branch: | bzr merge lp:~pete-woods/qtcreator-plugin-ubuntu/new-scope-template |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Benjamin Zeller | Approve | ||
PS Jenkins bot | continuous-integration | Approve | |
Review via email: mp+233218@code.launchpad.net |
Commit message
New scope template that talks to openweather API
Description of the change
New scope template that talks to openweather API
- 253. By Pete Woods
-
Process-cpp is used only for testing
- 254. By Pete Woods
-
Update images
PS Jenkins bot (ps-jenkins) wrote : | # |
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:254
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 255. By Pete Woods
-
Add documentation to the examples
- 256. By Pete Woods
-
Document the CMakeLists.txt code
- 257. By Pete Woods
-
It's a png
- 258. By Pete Woods
-
Typo
- 259. By Pete Woods
-
The scope is your own :)
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:256
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:259
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Preview Diff
1 | === modified file 'share/qtcreator/templates/wizards/ubuntu/scope/CMakeLists.txt' |
2 | --- share/qtcreator/templates/wizards/ubuntu/scope/CMakeLists.txt 2014-08-18 15:29:28 +0000 |
3 | +++ share/qtcreator/templates/wizards/ubuntu/scope/CMakeLists.txt 2014-09-03 15:09:42 +0000 |
4 | @@ -1,23 +1,69 @@ |
5 | project(%ProjectName:l% CXX) |
6 | cmake_minimum_required(VERSION 2.8.10) |
7 | -set(SCOPE_NAME %ClickHookName:l%) |
8 | -set(SCOPE_LIB_TARGET_NAME %ClickDomain:l%.%ProjectName:l%_%ClickHookName:l%) |
9 | - |
10 | -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -pedantic -Wall -Wextra") |
11 | +set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake" "${CMAKE_MODULE_PATH}") |
12 | + |
13 | +# We require g++ 4.9, to avoid ABI breakage with earlier version. |
14 | +set(cxx_version_required 4.9) |
15 | +if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") |
16 | + if (NOT CMAKE_CXX_COMPILER_VERSION MATCHES "^${cxx_version_required}") |
17 | + message(FATAL_ERROR "g++ version must be ${cxx_version_required}!") |
18 | + endif() |
19 | +endif() |
20 | + |
21 | +# Set strict and naggy C++ compiler flags, and enable C++11 |
22 | +add_definitions( |
23 | + -fno-permissive |
24 | + -std=c++11 |
25 | + -pedantic |
26 | + -Wall |
27 | + -Wextra |
28 | + -fPIC |
29 | +) |
30 | + |
31 | +include(GNUInstallDirs) |
32 | +find_package(PkgConfig) |
33 | + |
34 | +# We depend on Boost for string trimming |
35 | +find_package( |
36 | + Boost |
37 | + REQUIRED |
38 | +) |
39 | + |
40 | +# Search for our dependencies |
41 | +pkg_check_modules( |
42 | + SCOPE |
43 | + libunity-scopes>=0.6.0 |
44 | + jsoncpp |
45 | + net-cpp>=1.1.0 |
46 | + REQUIRED |
47 | +) |
48 | + |
49 | +# Add our dependencies to the include paths |
50 | +include_directories( |
51 | + "${CMAKE_SOURCE_DIR}/include" |
52 | + ${Boost_INCLUDE_DIRS} |
53 | + ${SCOPE_INCLUDE_DIRS} |
54 | +) |
55 | + |
56 | set(UBUNTU_PROJECT_TYPE "Scope" CACHE INTERNAL "Tells QtCreator this is a Scope project") |
57 | - |
58 | -set(INI_INSTALLDIR "/${SCOPE_NAME}") |
59 | -set(SCOPE_INSTALLDIR "/${SCOPE_NAME}") |
60 | - |
61 | -include(FindPkgConfig) |
62 | -pkg_check_modules(UNITY_SCOPES libunity-scopes>=0.5.0 REQUIRED) |
63 | - |
64 | +set(SCOPE_INSTALL_DIR "/%ClickHookName:l%") |
65 | + |
66 | +# If we need to refer to the scope's name or package in code, these definitions will help |
67 | +add_definitions(-DPACKAGE_NAME="%ClickDomain:l%.%ProjectName:l%") |
68 | +add_definitions(-DSCOPE_NAME="%ClickDomain:l%.%ProjectName:l%_%ClickHookName:l%") |
69 | + |
70 | +# Install the click manifest |
71 | +install(FILES manifest.json DESTINATION "/") |
72 | +install(FILES "%ClickHookName:l%.apparmor" DESTINATION "/") |
73 | + |
74 | +# Add our main directories |
75 | add_subdirectory(src) |
76 | add_subdirectory(data) |
77 | + |
78 | +# Set up the tests |
79 | enable_testing() |
80 | -add_subdirectory(test) |
81 | - |
82 | -install(FILES manifest.json DESTINATION "/") |
83 | -install(FILES "%ClickHookName:l%.apparmor" DESTINATION "/") |
84 | - |
85 | -add_custom_target("%ProjectName:l%_ClickFiles" ALL SOURCES "%ClickHookName:l%.apparmor" "manifest.json") |
86 | +add_subdirectory(tests) |
87 | +add_custom_target( |
88 | + check |
89 | + ${CMAKE_CTEST_COMMAND} --force-new-ctest-process --output-on-failure |
90 | +) |
91 | |
92 | === added directory 'share/qtcreator/templates/wizards/ubuntu/scope/cmake' |
93 | === added file 'share/qtcreator/templates/wizards/ubuntu/scope/cmake/FindGMock.cmake' |
94 | --- share/qtcreator/templates/wizards/ubuntu/scope/cmake/FindGMock.cmake 1970-01-01 00:00:00 +0000 |
95 | +++ share/qtcreator/templates/wizards/ubuntu/scope/cmake/FindGMock.cmake 2014-09-03 15:09:42 +0000 |
96 | @@ -0,0 +1,12 @@ |
97 | +# Build with system gmock and embedded gtest |
98 | +set (GMOCK_INCLUDE_DIRS "/usr/include/gmock/include" CACHE PATH "gmock source include directory") |
99 | +set (GMOCK_SOURCE_DIR "/usr/src/gmock" CACHE PATH "gmock source directory") |
100 | +set (GTEST_INCLUDE_DIRS "${GMOCK_SOURCE_DIR}/gtest/include" CACHE PATH "gtest source include directory") |
101 | + |
102 | +add_subdirectory(${GMOCK_SOURCE_DIR} "${CMAKE_CURRENT_BINARY_DIR}/gmock") |
103 | + |
104 | +set(GTEST_LIBRARIES gtest) |
105 | +set(GTEST_MAIN_LIBRARIES gtest_main) |
106 | +set(GMOCK_LIBRARIES gmock gmock_main) |
107 | + |
108 | +set(GTEST_BOTH_LIBRARIES ${GTEST_LIBRARIES} ${GTEST_MAIN_LIBRARIES}) |
109 | |
110 | === modified file 'share/qtcreator/templates/wizards/ubuntu/scope/data/CMakeLists.txt' |
111 | --- share/qtcreator/templates/wizards/ubuntu/scope/data/CMakeLists.txt 2014-08-04 07:25:56 +0000 |
112 | +++ share/qtcreator/templates/wizards/ubuntu/scope/data/CMakeLists.txt 2014-09-03 15:09:42 +0000 |
113 | @@ -1,11 +1,16 @@ |
114 | -# Put the ini file in the build directory next to the scope |
115 | -# .so file so test tools can find both easily. |
116 | -configure_file( |
117 | - "%ClickDomain:l%.%ProjectName:l%_%ClickHookName:l%.ini.in" |
118 | - "${CMAKE_BINARY_DIR}/src/%ClickDomain:l%.%ProjectName:l%_%ClickHookName:l%.ini" |
119 | + |
120 | +# Install the scope ini file |
121 | +install( |
122 | + FILES "%ClickDomain:l%.%ProjectName:l%_%ClickHookName:l%.ini" |
123 | + DESTINATION ${SCOPE_INSTALL_DIR} |
124 | ) |
125 | |
126 | -INSTALL( |
127 | - FILES "${CMAKE_BINARY_DIR}/src/%ClickDomain:l%.%ProjectName:l%_%ClickHookName:l%.ini" |
128 | - DESTINATION "${INI_INSTALLDIR}" |
129 | +# Install the scope images |
130 | +install( |
131 | + FILES |
132 | + "icon.png" |
133 | + "logo.png" |
134 | + "screenshot.png" |
135 | + DESTINATION |
136 | + "${SCOPE_INSTALL_DIR}" |
137 | ) |
138 | |
139 | === added file 'share/qtcreator/templates/wizards/ubuntu/scope/data/displayName.ini' |
140 | --- share/qtcreator/templates/wizards/ubuntu/scope/data/displayName.ini 1970-01-01 00:00:00 +0000 |
141 | +++ share/qtcreator/templates/wizards/ubuntu/scope/data/displayName.ini 2014-09-03 15:09:42 +0000 |
142 | @@ -0,0 +1,9 @@ |
143 | +[ScopeConfig] |
144 | +DisplayName = %ProjectName:c% Scope |
145 | +Description = This is a %ProjectName:c% scope |
146 | +Art = screenshot.png |
147 | +Author = Firstname Lastname |
148 | +Icon = icon.png |
149 | + |
150 | +[Appearance] |
151 | +PageHeader.Logo = logo.png |
152 | |
153 | === removed file 'share/qtcreator/templates/wizards/ubuntu/scope/data/displayName.ini.in' |
154 | --- share/qtcreator/templates/wizards/ubuntu/scope/data/displayName.ini.in 2014-08-04 08:14:53 +0000 |
155 | +++ share/qtcreator/templates/wizards/ubuntu/scope/data/displayName.ini.in 1970-01-01 00:00:00 +0000 |
156 | @@ -1,8 +0,0 @@ |
157 | -[ScopeConfig] |
158 | -DisplayName = %ProjectName:c% Scope |
159 | -Description = This is a %ProjectName:c% scope |
160 | -Author = Firstname Lastname |
161 | -Art = %ProjectName:l%.Art |
162 | -Icon = %ProjectName:l%.Icon |
163 | -SearchHint = %ProjectName:l%.SearchHint |
164 | -HotKey = %ProjectName:l%.HotKey |
165 | |
166 | === added file 'share/qtcreator/templates/wizards/ubuntu/scope/data/icon.png' |
167 | Binary files share/qtcreator/templates/wizards/ubuntu/scope/data/icon.png 1970-01-01 00:00:00 +0000 and share/qtcreator/templates/wizards/ubuntu/scope/data/icon.png 2014-09-03 15:09:42 +0000 differ |
168 | === added file 'share/qtcreator/templates/wizards/ubuntu/scope/data/logo.png' |
169 | Binary files share/qtcreator/templates/wizards/ubuntu/scope/data/logo.png 1970-01-01 00:00:00 +0000 and share/qtcreator/templates/wizards/ubuntu/scope/data/logo.png 2014-09-03 15:09:42 +0000 differ |
170 | === added file 'share/qtcreator/templates/wizards/ubuntu/scope/data/screenshot.png' |
171 | Binary files share/qtcreator/templates/wizards/ubuntu/scope/data/screenshot.png 1970-01-01 00:00:00 +0000 and share/qtcreator/templates/wizards/ubuntu/scope/data/screenshot.png 2014-09-03 15:09:42 +0000 differ |
172 | === added directory 'share/qtcreator/templates/wizards/ubuntu/scope/include' |
173 | === added directory 'share/qtcreator/templates/wizards/ubuntu/scope/include/api' |
174 | === added file 'share/qtcreator/templates/wizards/ubuntu/scope/include/api/client.h' |
175 | --- share/qtcreator/templates/wizards/ubuntu/scope/include/api/client.h 1970-01-01 00:00:00 +0000 |
176 | +++ share/qtcreator/templates/wizards/ubuntu/scope/include/api/client.h 2014-09-03 15:09:42 +0000 |
177 | @@ -0,0 +1,121 @@ |
178 | +#ifndef API_CLIENT_H_ |
179 | +#define API_CLIENT_H_ |
180 | + |
181 | +#include <api/config.h> |
182 | + |
183 | +#include <atomic> |
184 | +#include <deque> |
185 | +#include <map> |
186 | +#include <string> |
187 | +#include <core/net/http/request.h> |
188 | +#include <core/net/uri.h> |
189 | + |
190 | +namespace Json { |
191 | +class Value; |
192 | +} |
193 | + |
194 | +namespace api { |
195 | + |
196 | +/** |
197 | + * Provide a nice way to access the HTTP API. |
198 | + * |
199 | + * We don't want our scope's code to be mixed together with HTTP and JSON handling. |
200 | + */ |
201 | +class Client { |
202 | +public: |
203 | + /** |
204 | + * Information about a City |
205 | + */ |
206 | + struct City { |
207 | + unsigned int id; |
208 | + std::string name; |
209 | + std::string country; |
210 | + }; |
211 | + |
212 | + /** |
213 | + * Temperature information for a day. |
214 | + */ |
215 | + struct Temp { |
216 | + double max; |
217 | + double min; |
218 | + double cur; |
219 | + }; |
220 | + |
221 | + /** |
222 | + * Weather information for a day. |
223 | + */ |
224 | + struct Weather { |
225 | + unsigned int id; |
226 | + std::string main; |
227 | + std::string description; |
228 | + std::string icon; |
229 | + Temp temp; |
230 | + }; |
231 | + |
232 | + /** |
233 | + * A list of weather information |
234 | + */ |
235 | + typedef std::deque<Weather> WeatherList; |
236 | + |
237 | + /** |
238 | + * Weather information about the current day |
239 | + */ |
240 | + struct Current { |
241 | + City city; |
242 | + Weather weather; |
243 | + }; |
244 | + |
245 | + /** |
246 | + * Forecast information about a city |
247 | + */ |
248 | + struct Forecast { |
249 | + City city; |
250 | + WeatherList weather; |
251 | + }; |
252 | + |
253 | + Client(Config::Ptr config); |
254 | + |
255 | + virtual ~Client() = default; |
256 | + |
257 | + /** |
258 | + * Get the current weather for the specified location |
259 | + */ |
260 | + virtual Current weather(const std::string &query); |
261 | + |
262 | + /** |
263 | + * Get the weather forecast for the specified location and duration |
264 | + */ |
265 | + virtual Forecast forecast_daily(const std::string &query, unsigned int days = 7); |
266 | + |
267 | + /** |
268 | + * Cancel any pending queries (this method can be called from a different thread) |
269 | + */ |
270 | + virtual void cancel(); |
271 | + |
272 | + virtual Config::Ptr config(); |
273 | + |
274 | +protected: |
275 | + void get(const core::net::Uri::Path &path, |
276 | + const core::net::Uri::QueryParameters ¶meters, |
277 | + Json::Value &root); |
278 | + |
279 | + /** |
280 | + * Progress callback that allows the query to cancel pending HTTP requests. |
281 | + */ |
282 | + core::net::http::Request::Progress::Next progress_report( |
283 | + const core::net::http::Request::Progress& progress); |
284 | + |
285 | + /** |
286 | + * Hang onto the configuration information |
287 | + */ |
288 | + Config::Ptr config_; |
289 | + |
290 | + /** |
291 | + * Thread-safe cancelled flag |
292 | + */ |
293 | + std::atomic<bool> cancelled_; |
294 | +}; |
295 | + |
296 | +} |
297 | + |
298 | +#endif // API_CLIENT_H_ |
299 | |
300 | === added file 'share/qtcreator/templates/wizards/ubuntu/scope/include/api/config.h' |
301 | --- share/qtcreator/templates/wizards/ubuntu/scope/include/api/config.h 1970-01-01 00:00:00 +0000 |
302 | +++ share/qtcreator/templates/wizards/ubuntu/scope/include/api/config.h 2014-09-03 15:09:42 +0000 |
303 | @@ -0,0 +1,25 @@ |
304 | +#ifndef API_CONFIG_H_ |
305 | +#define API_CONFIG_H_ |
306 | + |
307 | +#include <memory> |
308 | +#include <string> |
309 | + |
310 | +namespace api { |
311 | + |
312 | +struct Config { |
313 | + typedef std::shared_ptr<Config> Ptr; |
314 | + |
315 | + /* |
316 | + * The root of all API request URLs |
317 | + */ |
318 | + std::string apiroot { "http://api.openweathermap.org" }; |
319 | + |
320 | + /* |
321 | + * The custom HTTP user agent string for this library |
322 | + */ |
323 | + std::string user_agent { "example-network-scope 0.1; (foo)" }; |
324 | +}; |
325 | + |
326 | +} |
327 | + |
328 | +#endif /* API_CONFIG_H_ */ |
329 | |
330 | === added directory 'share/qtcreator/templates/wizards/ubuntu/scope/include/scope' |
331 | === added file 'share/qtcreator/templates/wizards/ubuntu/scope/include/scope/preview.h' |
332 | --- share/qtcreator/templates/wizards/ubuntu/scope/include/scope/preview.h 1970-01-01 00:00:00 +0000 |
333 | +++ share/qtcreator/templates/wizards/ubuntu/scope/include/scope/preview.h 2014-09-03 15:09:42 +0000 |
334 | @@ -0,0 +1,37 @@ |
335 | +#ifndef SCOPE_PREVIEW_H_ |
336 | +#define SCOPE_PREVIEW_H_ |
337 | + |
338 | +#include <unity/scopes/PreviewQueryBase.h> |
339 | + |
340 | +namespace unity { |
341 | +namespace scopes { |
342 | +class Result; |
343 | +} |
344 | +} |
345 | + |
346 | +namespace scope { |
347 | + |
348 | +/** |
349 | + * Represents an individual preview request. |
350 | + * |
351 | + * Each time a result is previewed in the UI a new Preview |
352 | + * object is created. |
353 | + */ |
354 | +class Preview: public unity::scopes::PreviewQueryBase { |
355 | +public: |
356 | + Preview(const unity::scopes::Result &result, |
357 | + const unity::scopes::ActionMetadata &metadata); |
358 | + |
359 | + ~Preview() = default; |
360 | + |
361 | + void cancelled() override; |
362 | + |
363 | + /** |
364 | + * Populates the reply object with preview information. |
365 | + */ |
366 | + void run(unity::scopes::PreviewReplyProxy const& reply) override; |
367 | +}; |
368 | + |
369 | +} |
370 | + |
371 | +#endif // SCOPE_PREVIEW_H_ |
372 | |
373 | === added file 'share/qtcreator/templates/wizards/ubuntu/scope/include/scope/query.h' |
374 | --- share/qtcreator/templates/wizards/ubuntu/scope/include/scope/query.h 1970-01-01 00:00:00 +0000 |
375 | +++ share/qtcreator/templates/wizards/ubuntu/scope/include/scope/query.h 2014-09-03 15:09:42 +0000 |
376 | @@ -0,0 +1,36 @@ |
377 | +#ifndef SCOPE_QUERY_H_ |
378 | +#define SCOPE_QUERY_H_ |
379 | + |
380 | +#include <api/client.h> |
381 | + |
382 | +#include <unity/scopes/SearchQueryBase.h> |
383 | +#include <unity/scopes/ReplyProxyFwd.h> |
384 | + |
385 | +namespace scope { |
386 | + |
387 | +/** |
388 | + * Represents an individual query. |
389 | + * |
390 | + * A new Query object will be constructed for each query. It is |
391 | + * given query information, metadata about the search, and |
392 | + * some scope-specific configuration. |
393 | + */ |
394 | +class Query: public unity::scopes::SearchQueryBase { |
395 | +public: |
396 | + Query(const unity::scopes::CannedQuery &query, |
397 | + const unity::scopes::SearchMetadata &metadata, api::Config::Ptr config); |
398 | + |
399 | + ~Query() = default; |
400 | + |
401 | + void cancelled() override; |
402 | + |
403 | + void run(const unity::scopes::SearchReplyProxy &reply) override; |
404 | + |
405 | +private: |
406 | + api::Client client_; |
407 | +}; |
408 | + |
409 | +} |
410 | + |
411 | +#endif // SCOPE_QUERY_H_ |
412 | + |
413 | |
414 | === added file 'share/qtcreator/templates/wizards/ubuntu/scope/include/scope/scope.h' |
415 | --- share/qtcreator/templates/wizards/ubuntu/scope/include/scope/scope.h 1970-01-01 00:00:00 +0000 |
416 | +++ share/qtcreator/templates/wizards/ubuntu/scope/include/scope/scope.h 2014-09-03 15:09:42 +0000 |
417 | @@ -0,0 +1,53 @@ |
418 | +#ifndef SCOPE_SCOPE_H_ |
419 | +#define SCOPE_SCOPE_H_ |
420 | + |
421 | +#include <api/config.h> |
422 | + |
423 | +#include <unity/scopes/ScopeBase.h> |
424 | +#include <unity/scopes/QueryBase.h> |
425 | +#include <unity/scopes/ReplyProxyFwd.h> |
426 | +#include <unity/scopes/QueryBase.h> |
427 | +#include <unity/scopes/PreviewQueryBase.h> |
428 | + |
429 | +namespace scope { |
430 | + |
431 | +/** |
432 | + * Defines the lifecycle of scope plugin, and acts as a factory |
433 | + * for Query and Preview objects. |
434 | + * |
435 | + * Note that the #preview and #search methods are each called on |
436 | + * different threads, so some form of interlocking is required |
437 | + * if shared data structures are used. |
438 | + */ |
439 | +class Scope: public unity::scopes::ScopeBase { |
440 | +public: |
441 | + /** |
442 | + * Called once at startup |
443 | + */ |
444 | + void start(std::string const&) override; |
445 | + |
446 | + /** |
447 | + * Called at shutdown |
448 | + */ |
449 | + void stop() override; |
450 | + |
451 | + /** |
452 | + * Called each time a new preview is requested |
453 | + */ |
454 | + unity::scopes::PreviewQueryBase::UPtr preview(const unity::scopes::Result&, |
455 | + const unity::scopes::ActionMetadata&) override; |
456 | + |
457 | + /** |
458 | + * Called each time a new query is requested |
459 | + */ |
460 | + unity::scopes::SearchQueryBase::UPtr search( |
461 | + unity::scopes::CannedQuery const& q, |
462 | + unity::scopes::SearchMetadata const&) override; |
463 | + |
464 | +protected: |
465 | + api::Config::Ptr config_; |
466 | +}; |
467 | + |
468 | +} |
469 | + |
470 | +#endif // SCOPE_SCOPE_H_ |
471 | |
472 | === modified file 'share/qtcreator/templates/wizards/ubuntu/scope/src/CMakeLists.txt' |
473 | --- share/qtcreator/templates/wizards/ubuntu/scope/src/CMakeLists.txt 2014-07-01 10:09:49 +0000 |
474 | +++ share/qtcreator/templates/wizards/ubuntu/scope/src/CMakeLists.txt 2014-09-03 15:09:42 +0000 |
475 | @@ -1,12 +1,51 @@ |
476 | -add_library( |
477 | - ${SCOPE_LIB_TARGET_NAME} SHARED |
478 | - %ClickHookName:l%-preview.cpp |
479 | - %ClickHookName:l%-query.cpp |
480 | - %ClickHookName:l%-scope.cpp |
481 | -) |
482 | -target_link_libraries(${SCOPE_LIB_TARGET_NAME} ${UNITY_SCOPES_LDFLAGS}) |
483 | -set_property(TARGET ${SCOPE_LIB_TARGET_NAME} PROPERTY COMPILE_FLAGS ${UNITY_SCOPES_CFLAGS}) |
484 | - |
485 | -install(TARGETS ${SCOPE_LIB_TARGET_NAME} |
486 | -LIBRARY DESTINATION "${SCOPE_INSTALLDIR}" |
487 | + |
488 | +# Put the ini file in the build directory next to the scope |
489 | +# .so file so test tools can find both easily. |
490 | +configure_file( |
491 | + "${CMAKE_SOURCE_DIR}/data/%ClickDomain:l%.%ProjectName:l%_%ClickHookName:l%.ini" |
492 | + "${CMAKE_CURRENT_BINARY_DIR}/%ClickDomain:l%.%ProjectName:l%_%ClickHookName:l%.ini" |
493 | + @ONLY |
494 | +) |
495 | + |
496 | +# Build an object library for the scope code |
497 | +add_library( |
498 | + scope-static OBJECT |
499 | + api/client.cpp |
500 | + scope/preview.cpp |
501 | + scope/query.cpp |
502 | + scope/scope.cpp |
503 | +) |
504 | + |
505 | +# Ensure we export all the symbols |
506 | +set_target_properties( |
507 | + scope-static |
508 | + PROPERTIES |
509 | + LINK_FLAGS "-Wl,--export-all-symbols" |
510 | +) |
511 | + |
512 | +# Build a shared library containing our scope code. |
513 | +# This will be the actual plugin that is loaded. |
514 | +add_library( |
515 | + scope SHARED |
516 | + $<TARGET_OBJECTS:scope-static> |
517 | +) |
518 | + |
519 | +# Link against the object library and our external library dependencies |
520 | +target_link_libraries( |
521 | + scope |
522 | + ${SCOPE_LDFLAGS} |
523 | + ${Boost_LIBRARIES} |
524 | +) |
525 | + |
526 | +# Set the correct library output name to conform to the securiry policy |
527 | +set_target_properties( |
528 | + scope |
529 | + PROPERTIES |
530 | + OUTPUT_NAME "%ClickDomain:l%.%ProjectName:l%_%ClickHookName:l%" |
531 | +) |
532 | + |
533 | +# Install the scope shared library |
534 | +install( |
535 | + TARGETS scope |
536 | + LIBRARY DESTINATION ${SCOPE_INSTALL_DIR} |
537 | ) |
538 | |
539 | === added directory 'share/qtcreator/templates/wizards/ubuntu/scope/src/api' |
540 | === added file 'share/qtcreator/templates/wizards/ubuntu/scope/src/api/client.cpp' |
541 | --- share/qtcreator/templates/wizards/ubuntu/scope/src/api/client.cpp 1970-01-01 00:00:00 +0000 |
542 | +++ share/qtcreator/templates/wizards/ubuntu/scope/src/api/client.cpp 2014-09-03 15:09:42 +0000 |
543 | @@ -0,0 +1,157 @@ |
544 | +#include <api/client.h> |
545 | + |
546 | +#include <core/net/error.h> |
547 | +#include <core/net/http/client.h> |
548 | +#include <core/net/http/content_type.h> |
549 | +#include <core/net/http/response.h> |
550 | +#include <json/json.h> |
551 | + |
552 | +namespace http = core::net::http; |
553 | +namespace json = Json; |
554 | +namespace net = core::net; |
555 | + |
556 | +using namespace api; |
557 | +using namespace std; |
558 | + |
559 | +Client::Client(Config::Ptr config) : |
560 | + config_(config), cancelled_(false) { |
561 | +} |
562 | + |
563 | +void Client::get(const net::Uri::Path &path, |
564 | + const net::Uri::QueryParameters ¶meters, json::Value &root) { |
565 | + // Create a new HTTP client |
566 | + auto client = http::make_client(); |
567 | + |
568 | + // Start building the request configuration |
569 | + http::Request::Configuration configuration; |
570 | + |
571 | + // Build the URI from its components |
572 | + net::Uri uri = net::make_uri(config_->apiroot, path, parameters); |
573 | + configuration.uri = client->uri_to_string(uri); |
574 | + |
575 | + // Give out a user agent string |
576 | + configuration.header.add("User-Agent", config_->user_agent); |
577 | + |
578 | + // Build a HTTP request object from our configuration |
579 | + auto request = client->head(configuration); |
580 | + |
581 | + try { |
582 | + // Synchronously make the HTTP request |
583 | + // We bind the cancellable callback to #progress_report |
584 | + auto response = request->execute( |
585 | + bind(&Client::progress_report, this, placeholders::_1)); |
586 | + |
587 | + // Check that we got a sensible HTTP status code |
588 | + if (response.status != http::Status::ok) { |
589 | + throw domain_error(root["error"].asString()); |
590 | + } |
591 | + |
592 | + // Parse the JSON from the response |
593 | + json::Reader reader; |
594 | + reader.parse(response.body, root); |
595 | + |
596 | + // Open weather map API error code can either be a string or int |
597 | + json::Value cod = root["cod"]; |
598 | + if ((cod.isString() && cod.asString() != "200") |
599 | + || (cod.isUInt() && cod.asUInt() != 200)) { |
600 | + throw domain_error(root["message"].asString()); |
601 | + } |
602 | + } catch (net::Error &) { |
603 | + } |
604 | +} |
605 | + |
606 | +Client::Current Client::weather(const string& query) { |
607 | + json::Value root; |
608 | + |
609 | + // Build a URI and get the contents. |
610 | + // The fist parameter forms the path part of the URI. |
611 | + // The second parameter forms the CGI parameters. |
612 | + get( { "data", "2.5", "weather" }, |
613 | + { { "q", query }, { "units", "metric" } }, root); |
614 | + // e.g. http://api.openweathermap.org/data/2.5/weather?q=QUERY&units=metric |
615 | + |
616 | + Current result; |
617 | + |
618 | + // Read out the city we found |
619 | + json::Value sys = root["sys"]; |
620 | + result.city.id = sys["id"].asUInt(); |
621 | + result.city.name = root["name"].asString(); |
622 | + result.city.country = sys["country"].asString(); |
623 | + |
624 | + // Read the weather |
625 | + json::Value weather = root["weather"].get(json::ArrayIndex(0), |
626 | + json::Value()); |
627 | + result.weather.id = weather["id"].asUInt(); |
628 | + result.weather.main = weather["main"].asString(); |
629 | + result.weather.description = weather["description"].asString(); |
630 | + result.weather.icon = "http://openweathermap.org/img/w/" |
631 | + + weather["icon"].asString() + ".png"; |
632 | + |
633 | + // Read the temps |
634 | + json::Value main = root["main"]; |
635 | + result.weather.temp.cur = main["temp"].asDouble(); |
636 | + result.weather.temp.max = main["temp_max"].asDouble(); |
637 | + result.weather.temp.min = main["temp_min"].asDouble(); |
638 | + |
639 | + return result; |
640 | +} |
641 | + |
642 | +Client::Forecast Client::forecast_daily(const string& query, unsigned int cnt) { |
643 | + json::Value root; |
644 | + |
645 | + // Build a URI and get the contents |
646 | + // The fist parameter forms the path part of the URI. |
647 | + // The second parameter forms the CGI parameters. |
648 | + get( { "data", "2.5", "forecast", "daily" }, { { "q", query }, { "units", |
649 | + "metric" }, { "cnt", to_string(cnt) } }, root); |
650 | + // e.g. http://api.openweathermap.org/data/2.5/forecast/daily/?q=QUERY&units=metric&cnt=7 |
651 | + |
652 | + Forecast result; |
653 | + |
654 | + // Read out the city we found |
655 | + json::Value city = root["city"]; |
656 | + result.city.id = city["id"].asUInt(); |
657 | + result.city.name = city["name"].asString(); |
658 | + result.city.country = city["country"].asString(); |
659 | + |
660 | + // Iterate through the weather data |
661 | + json::Value list = root["list"]; |
662 | + for (json::ArrayIndex index = 0; index < list.size(); ++index) { |
663 | + json::Value item = list.get(index, json::Value()); |
664 | + |
665 | + // Extract the first weather item |
666 | + json::Value weather_list = item["weather"]; |
667 | + json::Value weather = weather_list.get(json::ArrayIndex(0), |
668 | + json::Value()); |
669 | + |
670 | + // Extract the temperature data |
671 | + json::Value temp = item["temp"]; |
672 | + |
673 | + // Add a result to the weather list |
674 | + result.weather.emplace_back( |
675 | + Weather { weather["id"].asUInt(), weather["main"].asString(), |
676 | + weather["description"].asString(), |
677 | + "http://openweathermap.org/img/w/" |
678 | + + weather["icon"].asString() + ".png", Temp { |
679 | + temp["max"].asDouble(), temp["min"].asDouble(), |
680 | + 0.0 } }); |
681 | + } |
682 | + |
683 | + return result; |
684 | +} |
685 | + |
686 | +http::Request::Progress::Next Client::progress_report( |
687 | + const http::Request::Progress&) { |
688 | + |
689 | + return cancelled_ ? |
690 | + http::Request::Progress::Next::abort_operation : |
691 | + http::Request::Progress::Next::continue_operation; |
692 | +} |
693 | + |
694 | +void Client::cancel() { |
695 | + cancelled_ = true; |
696 | +} |
697 | + |
698 | +Config::Ptr Client::config() { |
699 | + return config_; |
700 | +} |
701 | |
702 | === removed file 'share/qtcreator/templates/wizards/ubuntu/scope/src/displayName-preview.cpp' |
703 | --- share/qtcreator/templates/wizards/ubuntu/scope/src/displayName-preview.cpp 2014-07-01 11:02:41 +0000 |
704 | +++ share/qtcreator/templates/wizards/ubuntu/scope/src/displayName-preview.cpp 1970-01-01 00:00:00 +0000 |
705 | @@ -1,49 +0,0 @@ |
706 | -#include"%ClickHookName:l%-preview.h" |
707 | - |
708 | -#include<unity/scopes/PreviewWidget.h> |
709 | -#include<unity/scopes/ColumnLayout.h> |
710 | -#include<unity/scopes/PreviewReply.h> |
711 | - |
712 | -using namespace unity::scopes; |
713 | - |
714 | -%ClickHookName:s%Preview::%ClickHookName:s%Preview(Result const& result, ActionMetadata const& metadata) : |
715 | - PreviewQueryBase(result, metadata) |
716 | -{ |
717 | -} |
718 | - |
719 | -%ClickHookName:s%Preview::~%ClickHookName:s%Preview() |
720 | -{ |
721 | -} |
722 | - |
723 | -void %ClickHookName:s%Preview::cancelled() |
724 | -{ |
725 | -} |
726 | - |
727 | -void %ClickHookName:s%Preview::run(unity::scopes::PreviewReplyProxy const& reply) |
728 | -{ |
729 | - PreviewWidgetList widgets; |
730 | - widgets.emplace_back(PreviewWidget(R"({"id": "header", "type": "header", "components" : { "title": "title", "subtitle": "author" } })")); |
731 | - widgets.emplace_back(PreviewWidget(R"({"id": "img", "type": "image", "components" : { "source": "screenshot-url" } })")); |
732 | - |
733 | - PreviewWidget w("img2", "image"); |
734 | - w.add_attribute_value("zoomable", Variant(false)); |
735 | - w.add_attribute_mapping("source", "screenshot-url"); |
736 | - widgets.emplace_back(w); |
737 | - |
738 | - ColumnLayout layout1col(1); |
739 | - layout1col.add_column({"header", "img", "img2"}); |
740 | - |
741 | - ColumnLayout layout2col(2); |
742 | - layout2col.add_column({"header", "img"}); |
743 | - layout2col.add_column({"img2"}); |
744 | - |
745 | - ColumnLayout layout3col(3); |
746 | - layout3col.add_column({"header"}); |
747 | - layout3col.add_column({"img"}); |
748 | - layout3col.add_column({"img2"}); |
749 | - |
750 | - reply->register_layout({layout1col, layout2col, layout3col}); |
751 | - reply->push(widgets); |
752 | - reply->push("author", Variant("Foo")); |
753 | - reply->push("screenshot-url", Variant("/path/to/image.png")); |
754 | -} |
755 | |
756 | === removed file 'share/qtcreator/templates/wizards/ubuntu/scope/src/displayName-preview.h' |
757 | --- share/qtcreator/templates/wizards/ubuntu/scope/src/displayName-preview.h 2014-07-01 11:02:41 +0000 |
758 | +++ share/qtcreator/templates/wizards/ubuntu/scope/src/displayName-preview.h 1970-01-01 00:00:00 +0000 |
759 | @@ -1,18 +0,0 @@ |
760 | -#ifndef DEMOPREVIEW_H |
761 | -#define DEMOPREVIEW_H |
762 | - |
763 | -#include<unity/scopes/PreviewQueryBase.h> |
764 | -#include<unity/scopes/Result.h> |
765 | -#include<unity/scopes/ActionMetadata.h> |
766 | - |
767 | -class %ClickHookName:s%Preview : public unity::scopes::PreviewQueryBase |
768 | -{ |
769 | -public: |
770 | - %ClickHookName:s%Preview(unity::scopes::Result const& result, unity::scopes::ActionMetadata const& metadata); |
771 | - ~%ClickHookName:s%Preview(); |
772 | - |
773 | - virtual void cancelled() override; |
774 | - virtual void run(unity::scopes::PreviewReplyProxy const& reply) override; |
775 | -}; |
776 | - |
777 | -#endif |
778 | |
779 | === removed file 'share/qtcreator/templates/wizards/ubuntu/scope/src/displayName-query.cpp' |
780 | --- share/qtcreator/templates/wizards/ubuntu/scope/src/displayName-query.cpp 2014-07-01 15:07:36 +0000 |
781 | +++ share/qtcreator/templates/wizards/ubuntu/scope/src/displayName-query.cpp 1970-01-01 00:00:00 +0000 |
782 | @@ -1,54 +0,0 @@ |
783 | -#include "%ClickHookName:l%-query.h" |
784 | -#include <unity/scopes/Annotation.h> |
785 | -#include <unity/scopes/CategorisedResult.h> |
786 | -#include <unity/scopes/CategoryRenderer.h> |
787 | -#include <unity/scopes/QueryBase.h> |
788 | -#include <unity/scopes/SearchReply.h> |
789 | - |
790 | -using namespace unity::scopes; |
791 | - |
792 | -namespace |
793 | -{ |
794 | -const static std::string CATEGORY_TEMPLATE = |
795 | - R"( |
796 | -{ |
797 | - "schema-version": 1, |
798 | - "template": { |
799 | - "category-layout": "grid", |
800 | - "card-size": "medium" |
801 | - }, |
802 | - "components": { |
803 | - "title": "title", |
804 | - "art" : { |
805 | - "field": "art" |
806 | - }, |
807 | - "subtitle": "subtitle" |
808 | - } |
809 | -} |
810 | -)"; |
811 | -} |
812 | - |
813 | -%ClickHookName:s%Query::%ClickHookName:s%Query(CannedQuery const& query, SearchMetadata const& metadata) : |
814 | - SearchQueryBase(query, metadata) |
815 | -{ |
816 | -} |
817 | - |
818 | -%ClickHookName:s%Query::~%ClickHookName:s%Query() |
819 | -{ |
820 | -} |
821 | - |
822 | -void %ClickHookName:s%Query::cancelled() |
823 | -{ |
824 | -} |
825 | - |
826 | -void %ClickHookName:s%Query::run(unity::scopes::SearchReplyProxy const& reply) |
827 | -{ |
828 | - CategoryRenderer rdr(CATEGORY_TEMPLATE); |
829 | - auto cat = reply->register_category("cat1", "Category 1", "", rdr); |
830 | - CategorisedResult res(cat); |
831 | - res.set_uri("uri"); |
832 | - res.set_title("scope-A: result 1 for query \"" + query().query_string() + "\""); |
833 | - res.set_art("http://design.ubuntu.com/wp-content/uploads/ubuntu-logo32.png"); |
834 | - res.set_dnd_uri("dnd_uri"); |
835 | - reply->push(res); |
836 | -} |
837 | |
838 | === removed file 'share/qtcreator/templates/wizards/ubuntu/scope/src/displayName-query.h' |
839 | --- share/qtcreator/templates/wizards/ubuntu/scope/src/displayName-query.h 2014-07-01 11:02:41 +0000 |
840 | +++ share/qtcreator/templates/wizards/ubuntu/scope/src/displayName-query.h 1970-01-01 00:00:00 +0000 |
841 | @@ -1,17 +0,0 @@ |
842 | -#ifndef DEMOQUERY_H |
843 | -#define DEMOQUERY_H |
844 | - |
845 | -#include <unity/scopes/SearchQueryBase.h> |
846 | -#include <unity/scopes/ReplyProxyFwd.h> |
847 | - |
848 | -class %ClickHookName:s%Query : public unity::scopes::SearchQueryBase |
849 | -{ |
850 | -public: |
851 | - %ClickHookName:s%Query(unity::scopes::CannedQuery const& query, unity::scopes::SearchMetadata const& metadata); |
852 | - ~%ClickHookName:s%Query(); |
853 | - virtual void cancelled() override; |
854 | - |
855 | - virtual void run(unity::scopes::SearchReplyProxy const& reply) override; |
856 | -}; |
857 | - |
858 | -#endif |
859 | |
860 | === removed file 'share/qtcreator/templates/wizards/ubuntu/scope/src/displayName-scope.cpp' |
861 | --- share/qtcreator/templates/wizards/ubuntu/scope/src/displayName-scope.cpp 2014-08-05 11:35:58 +0000 |
862 | +++ share/qtcreator/templates/wizards/ubuntu/scope/src/displayName-scope.cpp 1970-01-01 00:00:00 +0000 |
863 | @@ -1,49 +0,0 @@ |
864 | -#include "%ClickHookName:l%-scope.h" |
865 | -#include "%ClickHookName:l%-query.h" |
866 | -#include "%ClickHookName:l%-preview.h" |
867 | -#include <unity-scopes.h> |
868 | - |
869 | -using namespace unity::scopes; |
870 | - |
871 | -void %ClickHookName:s%Scope::start(std::string const&) |
872 | -{ |
873 | -} |
874 | - |
875 | -void %ClickHookName:s%Scope::stop() |
876 | -{ |
877 | -} |
878 | - |
879 | -SearchQueryBase::UPtr %ClickHookName:s%Scope::search(CannedQuery const &q, SearchMetadata const& metadata) |
880 | -{ |
881 | - SearchQueryBase::UPtr query(new %ClickHookName:s%Query(q, metadata)); |
882 | - return query; |
883 | -} |
884 | - |
885 | - |
886 | -PreviewQueryBase::UPtr %ClickHookName:s%Scope::preview(Result const& result, ActionMetadata const& metadata) { |
887 | - PreviewQueryBase::UPtr preview(new %ClickHookName:s%Preview(result, metadata)); |
888 | - return preview; |
889 | -} |
890 | - |
891 | -#define EXPORT __attribute__ ((visibility ("default"))) |
892 | - |
893 | -extern "C" |
894 | -{ |
895 | - |
896 | - EXPORT |
897 | - unity::scopes::ScopeBase* |
898 | - // cppcheck-suppress unusedFunction |
899 | - UNITY_SCOPE_CREATE_FUNCTION() |
900 | - { |
901 | - return new %ClickHookName:s%Scope(); |
902 | - } |
903 | - |
904 | - EXPORT |
905 | - void |
906 | - // cppcheck-suppress unusedFunction |
907 | - UNITY_SCOPE_DESTROY_FUNCTION(unity::scopes::ScopeBase* scope_base) |
908 | - { |
909 | - delete scope_base; |
910 | - } |
911 | - |
912 | -} |
913 | |
914 | === removed file 'share/qtcreator/templates/wizards/ubuntu/scope/src/displayName-scope.h' |
915 | --- share/qtcreator/templates/wizards/ubuntu/scope/src/displayName-scope.h 2014-08-05 11:35:58 +0000 |
916 | +++ share/qtcreator/templates/wizards/ubuntu/scope/src/displayName-scope.h 1970-01-01 00:00:00 +0000 |
917 | @@ -1,24 +0,0 @@ |
918 | -#ifndef DEMOSCOPE_H |
919 | -#define DEMOSCOPE_H |
920 | - |
921 | -#include <unity/scopes/ScopeBase.h> |
922 | -#include <unity/scopes/QueryBase.h> |
923 | -#include <unity/scopes/ReplyProxyFwd.h> |
924 | -#include <unity/scopes/QueryBase.h> |
925 | -#include <unity/scopes/PreviewQueryBase.h> |
926 | - |
927 | -class %ClickHookName:s%Scope : public unity::scopes::ScopeBase |
928 | -{ |
929 | -public: |
930 | - virtual void start(std::string const&) override; |
931 | - |
932 | - virtual void stop() override; |
933 | - |
934 | - unity::scopes::PreviewQueryBase::UPtr preview(const unity::scopes::Result& result, |
935 | - unity::scopes::ActionMetadata const& metadata) override; |
936 | - |
937 | - virtual unity::scopes::SearchQueryBase::UPtr search(unity::scopes::CannedQuery const& q, |
938 | - unity::scopes::SearchMetadata const& metadata) override; |
939 | -}; |
940 | - |
941 | -#endif |
942 | |
943 | === added directory 'share/qtcreator/templates/wizards/ubuntu/scope/src/scope' |
944 | === added file 'share/qtcreator/templates/wizards/ubuntu/scope/src/scope/preview.cpp' |
945 | --- share/qtcreator/templates/wizards/ubuntu/scope/src/scope/preview.cpp 1970-01-01 00:00:00 +0000 |
946 | +++ share/qtcreator/templates/wizards/ubuntu/scope/src/scope/preview.cpp 2014-09-03 15:09:42 +0000 |
947 | @@ -0,0 +1,60 @@ |
948 | +#include <scope/preview.h> |
949 | + |
950 | +#include <unity/scopes/ColumnLayout.h> |
951 | +#include <unity/scopes/PreviewWidget.h> |
952 | +#include <unity/scopes/PreviewReply.h> |
953 | +#include <unity/scopes/Result.h> |
954 | +#include <unity/scopes/VariantBuilder.h> |
955 | + |
956 | +#include <iostream> |
957 | + |
958 | +namespace sc = unity::scopes; |
959 | + |
960 | +using namespace std; |
961 | +using namespace scope; |
962 | + |
963 | +Preview::Preview(const sc::Result &result, const sc::ActionMetadata &metadata) : |
964 | + sc::PreviewQueryBase(result, metadata) { |
965 | +} |
966 | + |
967 | +void Preview::cancelled() { |
968 | +} |
969 | + |
970 | +void Preview::run(sc::PreviewReplyProxy const& reply) { |
971 | + // Support three different column layouts |
972 | + sc::ColumnLayout layout1col(1), layout2col(2), layout3col(3); |
973 | + |
974 | + // Single column layout |
975 | + layout1col.add_column( { "image", "header", "summary" }); |
976 | + |
977 | + // Two column layout |
978 | + layout2col.add_column( { "image" }); |
979 | + layout2col.add_column( { "header", "summary" }); |
980 | + |
981 | + // Three cokumn layout |
982 | + layout3col.add_column( { "image" }); |
983 | + layout3col.add_column( { "header", "summary" }); |
984 | + layout3col.add_column( { }); |
985 | + |
986 | + // Register the layouts we just created |
987 | + reply->register_layout( { layout1col, layout2col, layout3col }); |
988 | + |
989 | + // Define the header section |
990 | + sc::PreviewWidget header("header", "header"); |
991 | + // It has title and a subtitle properties |
992 | + header.add_attribute_mapping("title", "title"); |
993 | + header.add_attribute_mapping("subtitle", "subtitle"); |
994 | + |
995 | + // Define the image section |
996 | + sc::PreviewWidget image("image", "image"); |
997 | + // It has a single source property, mapped to the result's art property |
998 | + image.add_attribute_mapping("source", "art"); |
999 | + |
1000 | + // Define the summary section |
1001 | + sc::PreviewWidget description("summary", "text"); |
1002 | + // It has a text property, mapped to the result's description property |
1003 | + description.add_attribute_mapping("text", "description"); |
1004 | + |
1005 | + // Push each of the sections |
1006 | + reply->push( { image, header, description }); |
1007 | +} |
1008 | |
1009 | === added file 'share/qtcreator/templates/wizards/ubuntu/scope/src/scope/query.cpp' |
1010 | --- share/qtcreator/templates/wizards/ubuntu/scope/src/scope/query.cpp 1970-01-01 00:00:00 +0000 |
1011 | +++ share/qtcreator/templates/wizards/ubuntu/scope/src/scope/query.cpp 2014-09-03 15:09:42 +0000 |
1012 | @@ -0,0 +1,177 @@ |
1013 | +#include <boost/algorithm/string/trim.hpp> |
1014 | + |
1015 | +#include <scope/query.h> |
1016 | + |
1017 | +#include <unity/scopes/Annotation.h> |
1018 | +#include <unity/scopes/CategorisedResult.h> |
1019 | +#include <unity/scopes/CategoryRenderer.h> |
1020 | +#include <unity/scopes/QueryBase.h> |
1021 | +#include <unity/scopes/SearchReply.h> |
1022 | + |
1023 | +#include <iomanip> |
1024 | +#include <sstream> |
1025 | + |
1026 | +namespace sc = unity::scopes; |
1027 | +namespace alg = boost::algorithm; |
1028 | + |
1029 | +using namespace std; |
1030 | +using namespace api; |
1031 | +using namespace scope; |
1032 | + |
1033 | +/** |
1034 | + * Define the layout for the forecast results |
1035 | + * |
1036 | + * The icon size is small, and ask for the card layout |
1037 | + * itself to be horizontal. I.e. the text will be placed |
1038 | + * next to the image. |
1039 | + */ |
1040 | +const static string WEATHER_TEMPLATE = |
1041 | + R"( |
1042 | +{ |
1043 | + "schema-version": 1, |
1044 | + "template": { |
1045 | + "category-layout": "grid", |
1046 | + "card-layout": "horizontal", |
1047 | + "card-size": "small" |
1048 | + }, |
1049 | + "components": { |
1050 | + "title": "title", |
1051 | + "art" : { |
1052 | + "field": "art" |
1053 | + }, |
1054 | + "subtitle": "subtitle" |
1055 | + } |
1056 | +} |
1057 | +)"; |
1058 | + |
1059 | +/** |
1060 | + * Define the larger "current weather" layout. |
1061 | + * |
1062 | + * The icons are larger. |
1063 | + */ |
1064 | +const static string CITY_TEMPLATE = |
1065 | + R"( |
1066 | +{ |
1067 | + "schema-version": 1, |
1068 | + "template": { |
1069 | + "category-layout": "grid", |
1070 | + "card-size": "medium" |
1071 | + }, |
1072 | + "components": { |
1073 | + "title": "title", |
1074 | + "art" : { |
1075 | + "field": "art" |
1076 | + }, |
1077 | + "subtitle": "subtitle" |
1078 | + } |
1079 | +} |
1080 | +)"; |
1081 | + |
1082 | +Query::Query(const sc::CannedQuery &query, const sc::SearchMetadata &metadata, |
1083 | + Config::Ptr config) : |
1084 | + sc::SearchQueryBase(query, metadata), client_(config) { |
1085 | +} |
1086 | + |
1087 | +void Query::cancelled() { |
1088 | + client_.cancel(); |
1089 | +} |
1090 | + |
1091 | +void Query::run(sc::SearchReplyProxy const& reply) { |
1092 | + try { |
1093 | + // Start by getting information about the query |
1094 | + const sc::CannedQuery &query(sc::SearchQueryBase::query()); |
1095 | + |
1096 | + // Trim the query string of whitespace |
1097 | + string query_string = alg::trim_copy(query.query_string()); |
1098 | + |
1099 | + Client::Current current; |
1100 | + if (query_string.empty()) { |
1101 | + // If the string is empty, get the current weather for London |
1102 | + current = client_.weather("London,uk"); |
1103 | + } else { |
1104 | + // otherwise, get the current weather for the search string |
1105 | + current = client_.weather(query_string); |
1106 | + } |
1107 | + |
1108 | + // Build up the description for the city |
1109 | + stringstream ss(stringstream::in | stringstream::out); |
1110 | + ss << current.city.name << ", " << current.city.country; |
1111 | + |
1112 | + // Register a category for the current weather, with the title we just built |
1113 | + auto location_cat = reply->register_category("current", ss.str(), "", |
1114 | + sc::CategoryRenderer(CITY_TEMPLATE)); |
1115 | + |
1116 | + { |
1117 | + // Create a single result for the current weather category |
1118 | + sc::CategorisedResult res(location_cat); |
1119 | + |
1120 | + // We must have a URI |
1121 | + res.set_uri(to_string(current.city.id)); |
1122 | + |
1123 | + // Build up the description for the current weather |
1124 | + stringstream ss(stringstream::in | stringstream::out); |
1125 | + ss << setprecision(3) << current.weather.temp.cur; |
1126 | + ss << "°C"; |
1127 | + res.set_title(ss.str()); |
1128 | + |
1129 | + // Set the rest of the attributes, art, description, etc |
1130 | + res.set_art(current.weather.icon); |
1131 | + res["subtitle"] = current.weather.description; |
1132 | + res["description"] = "A description of the result"; |
1133 | + |
1134 | + // Push the result |
1135 | + if (!reply->push(res)) { |
1136 | + // If we fail to push, it means the query has been cancelled. |
1137 | + // So don't continue; |
1138 | + return; |
1139 | + } |
1140 | + } |
1141 | + |
1142 | + Client::Forecast forecast; |
1143 | + if (query_string.empty()) { |
1144 | + // If there is no search string, get the forecast for London |
1145 | + forecast = client_.forecast_daily("London,uk"); |
1146 | + } else { |
1147 | + // otherwise, get the forecast for the search string |
1148 | + forecast = client_.forecast_daily(query_string); |
1149 | + } |
1150 | + |
1151 | + // Register a category for the forecast |
1152 | + auto forecast_cat = reply->register_category("forecast", |
1153 | + "7 day forecast", "", sc::CategoryRenderer(WEATHER_TEMPLATE)); |
1154 | + |
1155 | + // For each of the forecast days |
1156 | + for (const auto &weather : forecast.weather) { |
1157 | + // Create a result |
1158 | + sc::CategorisedResult res(forecast_cat); |
1159 | + |
1160 | + // We must have a URI |
1161 | + res.set_uri(to_string(weather.id)); |
1162 | + |
1163 | + // Build the description for the result |
1164 | + stringstream ss(stringstream::in | stringstream::out); |
1165 | + ss << setprecision(3) << weather.temp.max; |
1166 | + ss << "°C to "; |
1167 | + ss << setprecision(3) << weather.temp.min; |
1168 | + ss << "°C"; |
1169 | + res.set_title(ss.str()); |
1170 | + |
1171 | + // Set the rest of the attributes |
1172 | + res.set_art(weather.icon); |
1173 | + res["subtitle"] = weather.description; |
1174 | + res["description"] = "A description of the result"; |
1175 | + |
1176 | + // Push the result |
1177 | + if (!reply->push(res)) { |
1178 | + // If we fail to push, it means the query has been cancelled. |
1179 | + // So don't continue; |
1180 | + return; |
1181 | + } |
1182 | + } |
1183 | + |
1184 | + } catch (domain_error &e) { |
1185 | + // Handle exceptions being thrown by the client API |
1186 | + cerr << e.what() << endl; |
1187 | + reply->error(current_exception()); |
1188 | + } |
1189 | +} |
1190 | |
1191 | === added file 'share/qtcreator/templates/wizards/ubuntu/scope/src/scope/scope.cpp' |
1192 | --- share/qtcreator/templates/wizards/ubuntu/scope/src/scope/scope.cpp 1970-01-01 00:00:00 +0000 |
1193 | +++ share/qtcreator/templates/wizards/ubuntu/scope/src/scope/scope.cpp 2014-09-03 15:09:42 +0000 |
1194 | @@ -0,0 +1,58 @@ |
1195 | +#include <scope/scope.h> |
1196 | +#include <scope/query.h> |
1197 | +#include <scope/preview.h> |
1198 | + |
1199 | +#include <iostream> |
1200 | +#include <sstream> |
1201 | +#include <fstream> |
1202 | + |
1203 | +namespace sc = unity::scopes; |
1204 | +using namespace std; |
1205 | +using namespace api; |
1206 | +using namespace scope; |
1207 | + |
1208 | +void Scope::start(string const&) { |
1209 | + config_ = make_shared<Config>(); |
1210 | + |
1211 | + // Under test we set a different API root |
1212 | + char *apiroot = getenv("NETWORK_SCOPE_APIROOT"); |
1213 | + if (apiroot) { |
1214 | + config_->apiroot = apiroot; |
1215 | + } |
1216 | +} |
1217 | + |
1218 | +void Scope::stop() { |
1219 | +} |
1220 | + |
1221 | +sc::SearchQueryBase::UPtr Scope::search(const sc::CannedQuery &query, |
1222 | + const sc::SearchMetadata &metadata) { |
1223 | + // Boilerplate construction of Query |
1224 | + return sc::SearchQueryBase::UPtr(new Query(query, metadata, config_)); |
1225 | +} |
1226 | + |
1227 | +sc::PreviewQueryBase::UPtr Scope::preview(sc::Result const& result, |
1228 | + sc::ActionMetadata const& metadata) { |
1229 | + // Boilerplate construction of Preview |
1230 | + return sc::PreviewQueryBase::UPtr(new Preview(result, metadata)); |
1231 | +} |
1232 | + |
1233 | +#define EXPORT __attribute__ ((visibility ("default"))) |
1234 | + |
1235 | +// These functions define the entry points for the scope plugin |
1236 | +extern "C" { |
1237 | + |
1238 | +EXPORT |
1239 | +unity::scopes::ScopeBase* |
1240 | +// cppcheck-suppress unusedFunction |
1241 | +UNITY_SCOPE_CREATE_FUNCTION() { |
1242 | + return new Scope(); |
1243 | +} |
1244 | + |
1245 | +EXPORT |
1246 | +void |
1247 | +// cppcheck-suppress unusedFunction |
1248 | +UNITY_SCOPE_DESTROY_FUNCTION(unity::scopes::ScopeBase* scope_base) { |
1249 | + delete scope_base; |
1250 | +} |
1251 | + |
1252 | +} |
1253 | |
1254 | === removed directory 'share/qtcreator/templates/wizards/ubuntu/scope/test' |
1255 | === removed file 'share/qtcreator/templates/wizards/ubuntu/scope/test/CMakeLists.txt' |
1256 | --- share/qtcreator/templates/wizards/ubuntu/scope/test/CMakeLists.txt 2014-05-15 10:14:07 +0000 |
1257 | +++ share/qtcreator/templates/wizards/ubuntu/scope/test/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
1258 | @@ -1,2 +0,0 @@ |
1259 | -add_executable(simpletest simpletest.cpp) |
1260 | -add_test(simpletest simpletest) |
1261 | |
1262 | === removed file 'share/qtcreator/templates/wizards/ubuntu/scope/test/simpletest.cpp' |
1263 | --- share/qtcreator/templates/wizards/ubuntu/scope/test/simpletest.cpp 2014-05-15 10:14:07 +0000 |
1264 | +++ share/qtcreator/templates/wizards/ubuntu/scope/test/simpletest.cpp 1970-01-01 00:00:00 +0000 |
1265 | @@ -1,3 +0,0 @@ |
1266 | -int main(int, char**) { |
1267 | - return 0; |
1268 | -} |
1269 | |
1270 | === added directory 'share/qtcreator/templates/wizards/ubuntu/scope/tests' |
1271 | === added file 'share/qtcreator/templates/wizards/ubuntu/scope/tests/CMakeLists.txt' |
1272 | --- share/qtcreator/templates/wizards/ubuntu/scope/tests/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
1273 | +++ share/qtcreator/templates/wizards/ubuntu/scope/tests/CMakeLists.txt 2014-09-03 15:09:42 +0000 |
1274 | @@ -0,0 +1,25 @@ |
1275 | + |
1276 | +# Google Mock unfortunately has to be compiled from source |
1277 | +include(FindGMock) |
1278 | + |
1279 | +# We need process-cpp to launch the python test server |
1280 | +pkg_check_modules( |
1281 | + TEST |
1282 | + process-cpp |
1283 | + REQUIRED |
1284 | +) |
1285 | + |
1286 | +# Include our test library headers |
1287 | +include_directories( |
1288 | + ${GTEST_INCLUDE_DIRS} |
1289 | + ${GMOCK_INCLUDE_DIRS} |
1290 | + ${TEST_INCLUDE_DIRS} |
1291 | +) |
1292 | + |
1293 | +# Where to find the test server binary |
1294 | +add_definitions( |
1295 | + -DFAKE_SERVER="${CMAKE_CURRENT_SOURCE_DIR}/server/server.py" |
1296 | +) |
1297 | + |
1298 | +# Add the unit tests |
1299 | +add_subdirectory(unit) |
1300 | |
1301 | === added directory 'share/qtcreator/templates/wizards/ubuntu/scope/tests/server' |
1302 | === added directory 'share/qtcreator/templates/wizards/ubuntu/scope/tests/server/forecast' |
1303 | === added directory 'share/qtcreator/templates/wizards/ubuntu/scope/tests/server/forecast/daily' |
1304 | === added file 'share/qtcreator/templates/wizards/ubuntu/scope/tests/server/forecast/daily/London,uk.json' |
1305 | --- share/qtcreator/templates/wizards/ubuntu/scope/tests/server/forecast/daily/London,uk.json 1970-01-01 00:00:00 +0000 |
1306 | +++ share/qtcreator/templates/wizards/ubuntu/scope/tests/server/forecast/daily/London,uk.json 2014-09-03 15:09:42 +0000 |
1307 | @@ -0,0 +1,1 @@ |
1308 | +{"cod":"200","message":0.1117,"city":{"id":2643743,"name":"London","coord":{"lon":-0.12574,"lat":51.50853},"country":"GB","population":0,"sys":{"population":0}},"cnt":7,"list":[{"dt":1407412800,"temp":{"day":23.33,"min":18.84,"max":25.09,"night":18.84,"eve":24.17,"morn":20.76},"pressure":1018.23,"humidity":83,"weather":[{"id":500,"main":"Rain","description":"light rain","icon":"10d"}],"speed":1.87,"deg":295,"clouds":12,"rain":0.5},{"dt":1407499200,"temp":{"day":19.44,"min":15.54,"max":20.86,"night":15.54,"eve":18.28,"morn":16.21},"pressure":1010.57,"humidity":97,"weather":[{"id":501,"main":"Rain","description":"moderate rain","icon":"10d"}],"speed":4.01,"deg":143,"clouds":92,"rain":8},{"dt":1407585600,"temp":{"day":18.78,"min":13.19,"max":19.58,"night":13.19,"eve":18.95,"morn":14.03},"pressure":1010.78,"humidity":83,"weather":[{"id":802,"main":"Clouds","description":"scattered clouds","icon":"03d"}],"speed":5.46,"deg":281,"clouds":32},{"dt":1407672000,"temp":{"day":18.09,"min":13.46,"max":18.09,"night":13.46,"eve":16.58,"morn":13.91},"pressure":1002.33,"humidity":67,"weather":[{"id":501,"main":"Rain","description":"moderate rain","icon":"10d"}],"speed":10.68,"deg":162,"clouds":92,"rain":4},{"dt":1407758400,"temp":{"day":17.38,"min":15.39,"max":17.38,"night":16.3,"eve":17.03,"morn":15.39},"pressure":1008.2,"humidity":0,"weather":[{"id":502,"main":"Rain","description":"heavy intensity rain","icon":"10d"}],"speed":13.52,"deg":245,"clouds":74,"rain":12.63},{"dt":1407844800,"temp":{"day":18.44,"min":16.17,"max":18.44,"night":16.83,"eve":18.02,"morn":16.17},"pressure":1009.94,"humidity":0,"weather":[{"id":501,"main":"Rain","description":"moderate rain","icon":"10d"}],"speed":10.93,"deg":251,"clouds":60,"rain":5.25},{"dt":1407931200,"temp":{"day":18.8,"min":16.67,"max":19.02,"night":16.77,"eve":19.02,"morn":16.67},"pressure":1013.17,"humidity":0,"weather":[{"id":500,"main":"Rain","description":"light rain","icon":"10d"}],"speed":9.88,"deg":275,"clouds":85,"rain":1.35}]} |
1309 | |
1310 | === added file 'share/qtcreator/templates/wizards/ubuntu/scope/tests/server/forecast/daily/Manchester,uk.json' |
1311 | --- share/qtcreator/templates/wizards/ubuntu/scope/tests/server/forecast/daily/Manchester,uk.json 1970-01-01 00:00:00 +0000 |
1312 | +++ share/qtcreator/templates/wizards/ubuntu/scope/tests/server/forecast/daily/Manchester,uk.json 2014-09-03 15:09:42 +0000 |
1313 | @@ -0,0 +1,1 @@ |
1314 | +{"cod":"200","message":0.0056,"city":{"id":2643123,"name":"Manchester","coord":{"lon":-2.23743,"lat":53.480949},"country":"GB","population":0,"sys":{"population":0}},"cnt":7,"list":[{"dt":1407412800,"temp":{"day":17.91,"min":11.96,"max":18.83,"night":11.96,"eve":18.01,"morn":16.13},"pressure":1014.82,"humidity":77,"weather":[{"id":800,"main":"Clear","description":"sky is clear","icon":"01d"}],"speed":3.32,"deg":303,"clouds":0},{"dt":1407499200,"temp":{"day":18.59,"min":12.33,"max":18.59,"night":12.33,"eve":14.55,"morn":14.69},"pressure":1008.22,"humidity":79,"weather":[{"id":501,"main":"Rain","description":"moderate rain","icon":"10d"}],"speed":3.46,"deg":163,"clouds":92,"rain":11},{"dt":1407585600,"temp":{"day":15.8,"min":10.79,"max":17.11,"night":10.79,"eve":16.89,"morn":13.19},"pressure":1005.76,"humidity":92,"weather":[{"id":803,"main":"Clouds","description":"broken clouds","icon":"04d"}],"speed":5.61,"deg":279,"clouds":56},{"dt":1407672000,"temp":{"day":15.29,"min":12.21,"max":15.98,"night":12.41,"eve":15.98,"morn":12.21},"pressure":995.36,"humidity":95,"weather":[{"id":501,"main":"Rain","description":"moderate rain","icon":"10d"}],"speed":10.75,"deg":137,"clouds":92,"rain":5},{"dt":1407758400,"temp":{"day":15.73,"min":12.99,"max":15.73,"night":13.8,"eve":15.23,"morn":12.99},"pressure":990.16,"humidity":0,"weather":[{"id":500,"main":"Rain","description":"light rain","icon":"10d"}],"speed":9.02,"deg":239,"clouds":99,"rain":1.15},{"dt":1407844800,"temp":{"day":17.64,"min":14.08,"max":17.64,"night":14.08,"eve":14.92,"morn":14.12},"pressure":992.52,"humidity":0,"weather":[{"id":501,"main":"Rain","description":"moderate rain","icon":"10d"}],"speed":10.36,"deg":240,"clouds":45,"rain":4.84},{"dt":1407931200,"temp":{"day":14.35,"min":13.37,"max":15.52,"night":13.77,"eve":15.52,"morn":13.37},"pressure":999.39,"humidity":0,"weather":[{"id":501,"main":"Rain","description":"moderate rain","icon":"10d"}],"speed":7.79,"deg":285,"clouds":92,"rain":5.98}]} |
1315 | |
1316 | === added file 'share/qtcreator/templates/wizards/ubuntu/scope/tests/server/server.py' |
1317 | --- share/qtcreator/templates/wizards/ubuntu/scope/tests/server/server.py 1970-01-01 00:00:00 +0000 |
1318 | +++ share/qtcreator/templates/wizards/ubuntu/scope/tests/server/server.py 2014-09-03 15:09:42 +0000 |
1319 | @@ -0,0 +1,51 @@ |
1320 | +#!/usr/bin/env python3 |
1321 | + |
1322 | +import http.server |
1323 | +import os |
1324 | +import socketserver |
1325 | +import sys |
1326 | +from urllib.parse import urlparse,parse_qs |
1327 | + |
1328 | +def read_file(path): |
1329 | + file = os.path.join(os.path.dirname(__file__), path) |
1330 | + if os.path.isfile(file): |
1331 | + with open(file, 'r') as fp: |
1332 | + content = fp.read() |
1333 | + else: |
1334 | + content = '' |
1335 | + |
1336 | + return content |
1337 | + |
1338 | +class MyRequestHandler(http.server.BaseHTTPRequestHandler): |
1339 | + def do_GET(self): |
1340 | + sys.stderr.write("GET: %s\n" % self.path) |
1341 | + sys.stderr.flush() |
1342 | + |
1343 | + parse = urlparse(self.path) |
1344 | + path = parse.path |
1345 | + query = parse_qs(parse.query) |
1346 | + |
1347 | + if path == '/data/2.5/weather': |
1348 | + self.send_response(200) |
1349 | + self.send_header("Content-type", "text/html") |
1350 | + self.end_headers() |
1351 | + self.wfile.write(bytes(read_file('weather/%s.json' % query['q'][0]), 'UTF-8')) |
1352 | + elif path == '/data/2.5/forecast/daily': |
1353 | + self.send_response(200) |
1354 | + self.send_header("Content-type", "text/html") |
1355 | + self.end_headers() |
1356 | + self.wfile.write(bytes(read_file('forecast/daily/%s.json' % query['q'][0]), 'UTF-8')) |
1357 | + else: |
1358 | + self.send_response(404) |
1359 | + self.send_header("Content-type", "text/html") |
1360 | + self.end_headers() |
1361 | + self.wfile.write(bytes('ERROR', 'UTF-8')) |
1362 | + |
1363 | +if __name__ == "__main__": |
1364 | + Handler = MyRequestHandler |
1365 | + httpd = socketserver.TCPServer(("127.0.0.1", 0), Handler) |
1366 | + |
1367 | + sys.stdout.write('%d\n' % httpd.server_address[1]) |
1368 | + sys.stdout.flush() |
1369 | + |
1370 | + httpd.serve_forever() |
1371 | |
1372 | === added directory 'share/qtcreator/templates/wizards/ubuntu/scope/tests/server/weather' |
1373 | === added file 'share/qtcreator/templates/wizards/ubuntu/scope/tests/server/weather/London,uk.json' |
1374 | --- share/qtcreator/templates/wizards/ubuntu/scope/tests/server/weather/London,uk.json 1970-01-01 00:00:00 +0000 |
1375 | +++ share/qtcreator/templates/wizards/ubuntu/scope/tests/server/weather/London,uk.json 2014-09-03 15:09:42 +0000 |
1376 | @@ -0,0 +1,1 @@ |
1377 | +{"coord":{"lon":-0.13,"lat":51.51},"sys":{"type":1,"id":5091,"message":0.29,"country":"GB","sunrise":1407386057,"sunset":1407440289},"weather":[{"id":801,"main":"Clouds","description":"few clouds","icon":"02d"}],"base":"cmc stations","main":{"temp":21.83,"pressure":1014,"humidity":53,"temp_min":20,"temp_max":24},"wind":{"speed":1.5,"deg":0},"clouds":{"all":20},"dt":1407408276,"id":2643743,"name":"London","cod":200} |
1378 | \ No newline at end of file |
1379 | |
1380 | === added file 'share/qtcreator/templates/wizards/ubuntu/scope/tests/server/weather/Manchester,uk.json' |
1381 | --- share/qtcreator/templates/wizards/ubuntu/scope/tests/server/weather/Manchester,uk.json 1970-01-01 00:00:00 +0000 |
1382 | +++ share/qtcreator/templates/wizards/ubuntu/scope/tests/server/weather/Manchester,uk.json 2014-09-03 15:09:42 +0000 |
1383 | @@ -0,0 +1,1 @@ |
1384 | +{"coord":{"lon":-2.24,"lat":53.48},"sys":{"type":1,"id":5060,"message":0.2423,"country":"GB","sunrise":1407386141,"sunset":1407441219},"weather":[{"id":802,"main":"Clouds","description":"scattered clouds","icon":"03d"}],"base":"cmc stations","main":{"temp":17.35,"pressure":1016,"humidity":77,"temp_min":17,"temp_max":18},"wind":{"speed":2.6,"deg":20,"var_beg":330,"var_end":80},"clouds":{"all":40},"dt":1407408600,"id":2643123,"name":"Manchester","cod":200} |
1385 | |
1386 | === added directory 'share/qtcreator/templates/wizards/ubuntu/scope/tests/unit' |
1387 | === added file 'share/qtcreator/templates/wizards/ubuntu/scope/tests/unit/CMakeLists.txt' |
1388 | --- share/qtcreator/templates/wizards/ubuntu/scope/tests/unit/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
1389 | +++ share/qtcreator/templates/wizards/ubuntu/scope/tests/unit/CMakeLists.txt 2014-09-03 15:09:42 +0000 |
1390 | @@ -0,0 +1,24 @@ |
1391 | + |
1392 | +# Our test executable. |
1393 | +# It includes the object code from the scope |
1394 | +add_executable( |
1395 | + scope-unit-tests |
1396 | + scope/test-scope.cpp |
1397 | + $<TARGET_OBJECTS:scope-static> |
1398 | +) |
1399 | + |
1400 | +# Link against the scope, and all of our test lib dependencies |
1401 | +target_link_libraries( |
1402 | + scope-unit-tests |
1403 | + ${GTEST_BOTH_LIBRARIES} |
1404 | + ${GMOCK_LIBRARIES} |
1405 | + ${SCOPE_LDFLAGS} |
1406 | + ${TEST_LDFLAGS} |
1407 | + ${Boost_LIBRARIES} |
1408 | +) |
1409 | + |
1410 | +# Register the test with CTest |
1411 | +add_test( |
1412 | + scope-unit-tests |
1413 | + scope-unit-tests |
1414 | +) |
1415 | |
1416 | === added directory 'share/qtcreator/templates/wizards/ubuntu/scope/tests/unit/scope' |
1417 | === added file 'share/qtcreator/templates/wizards/ubuntu/scope/tests/unit/scope/test-scope.cpp' |
1418 | --- share/qtcreator/templates/wizards/ubuntu/scope/tests/unit/scope/test-scope.cpp 1970-01-01 00:00:00 +0000 |
1419 | +++ share/qtcreator/templates/wizards/ubuntu/scope/tests/unit/scope/test-scope.cpp 2014-09-03 15:09:42 +0000 |
1420 | @@ -0,0 +1,225 @@ |
1421 | +#include <scope/scope.h> |
1422 | + |
1423 | +#include <core/posix/exec.h> |
1424 | +#include <gtest/gtest.h> |
1425 | +#include <gmock/gmock.h> |
1426 | +#include <string> |
1427 | +#include <unity/scopes/SearchReply.h> |
1428 | +#include <unity/scopes/SearchReplyProxyFwd.h> |
1429 | +#include <unity/scopes/Variant.h> |
1430 | +#include <unity/scopes/testing/Category.h> |
1431 | +#include <unity/scopes/testing/MockSearchReply.h> |
1432 | +#include <unity/scopes/testing/TypedScopeFixture.h> |
1433 | + |
1434 | +using namespace std; |
1435 | +using namespace testing; |
1436 | +using namespace scope; |
1437 | + |
1438 | +namespace posix = core::posix; |
1439 | +namespace sc = unity::scopes; |
1440 | +namespace sct = unity::scopes::testing; |
1441 | + |
1442 | +/** |
1443 | + * Keep the tests in an anonymous namespace |
1444 | + */ |
1445 | +namespace { |
1446 | + |
1447 | +/** |
1448 | + * Custom matcher to check the properties of search results |
1449 | + */ |
1450 | +MATCHER_P2(ResultProp, prop, value, "") { |
1451 | + if (arg.contains(prop)) { |
1452 | + *result_listener << "result[" << prop << "] is " << arg[prop].serialize_json(); |
1453 | + } else { |
1454 | + *result_listener << "result[" << prop << "] is not set"; |
1455 | + } |
1456 | + return arg.contains(prop) && arg[prop] == sc::Variant(value); |
1457 | +} |
1458 | + |
1459 | +/** |
1460 | + * Custom matcher to check the presence of departments |
1461 | + */ |
1462 | +MATCHER_P(IsDepartment, department, "") { |
1463 | + return arg->serialize() == department->serialize(); |
1464 | +} |
1465 | + |
1466 | +typedef sct::TypedScopeFixture<Scope> TypedScopeFixtureScope; |
1467 | + |
1468 | +class TestScope: public TypedScopeFixtureScope { |
1469 | +protected: |
1470 | + void SetUp() override |
1471 | + { |
1472 | + // Start up Python-based fake OpenWeatherMap server |
1473 | + fake_server_ = posix::exec("/usr/bin/python3", { FAKE_SERVER }, { }, |
1474 | + posix::StandardStream::stdout); |
1475 | + |
1476 | + // Check it's running |
1477 | + ASSERT_GT(fake_server_.pid(), 0); |
1478 | + string port; |
1479 | + // The server will print out the random port it is using |
1480 | + fake_server_.cout() >> port; |
1481 | + // Check we have a port |
1482 | + ASSERT_FALSE(port.empty()); |
1483 | + |
1484 | + // Build up the API root |
1485 | + string apiroot = "http://127.0.0.1:" + port; |
1486 | + // Override the API root that the scope will use |
1487 | + setenv("NETWORK_SCOPE_APIROOT", apiroot.c_str(), true); |
1488 | + |
1489 | + // Do the parent SetUp |
1490 | + TypedScopeFixtureScope::SetUp(); |
1491 | + } |
1492 | + |
1493 | + /** |
1494 | + * Start by assuming the server is invalid |
1495 | + */ |
1496 | + posix::ChildProcess fake_server_ = posix::ChildProcess::invalid(); |
1497 | +}; |
1498 | + |
1499 | +TEST_F(TestScope, empty_search_string) { |
1500 | + const sc::CategoryRenderer renderer; |
1501 | + NiceMock<sct::MockSearchReply> reply; |
1502 | + |
1503 | + // Build a query with an empty search string |
1504 | + sc::CannedQuery query(SCOPE_NAME, "", ""); |
1505 | + |
1506 | + // Expect the current weather category |
1507 | + EXPECT_CALL(reply, register_category("current", "London, GB", "", _)).Times(1) |
1508 | + .WillOnce(Return(make_shared<sct::Category>("current", "London, GB", "", renderer))); |
1509 | + |
1510 | + // With one result |
1511 | + EXPECT_CALL(reply, push(Matcher<sc::CategorisedResult const&>(AllOf( |
1512 | + ResultProp("title", "21.8°C"), |
1513 | + ResultProp("art", "http://openweathermap.org/img/w/02d.png"), |
1514 | + ResultProp("subtitle", "few clouds") |
1515 | + )))).WillOnce( |
1516 | + Return(true)); |
1517 | + |
1518 | + // Expect the forecast category |
1519 | + EXPECT_CALL(reply, register_category("forecast", "7 day forecast", "", _)).Times(1) |
1520 | + .WillOnce(Return(make_shared<sct::Category>("forecast", "7 day forecast", "", renderer))); |
1521 | + |
1522 | + // With seven results |
1523 | + EXPECT_CALL(reply, push(Matcher<sc::CategorisedResult const&>(AllOf( |
1524 | + ResultProp("title", "25.1°C to 18.8°C"), |
1525 | + ResultProp("art", "http://openweathermap.org/img/w/10d.png"), |
1526 | + ResultProp("subtitle", "light rain") |
1527 | + )))).WillOnce(Return(true)); |
1528 | + EXPECT_CALL(reply, push(Matcher<sc::CategorisedResult const&>(AllOf( |
1529 | + ResultProp("title", "20.9°C to 15.5°C"), |
1530 | + ResultProp("art", "http://openweathermap.org/img/w/10d.png"), |
1531 | + ResultProp("subtitle", "moderate rain") |
1532 | + )))).WillOnce(Return(true)); |
1533 | + EXPECT_CALL(reply, push(Matcher<sc::CategorisedResult const&>(AllOf( |
1534 | + ResultProp("title", "19.6°C to 13.2°C"), |
1535 | + ResultProp("art", "http://openweathermap.org/img/w/03d.png"), |
1536 | + ResultProp("subtitle", "scattered clouds") |
1537 | + )))).WillOnce(Return(true)); |
1538 | + EXPECT_CALL(reply, push(Matcher<sc::CategorisedResult const&>(AllOf( |
1539 | + ResultProp("title", "18.1°C to 13.5°C"), |
1540 | + ResultProp("art", "http://openweathermap.org/img/w/10d.png"), |
1541 | + ResultProp("subtitle", "moderate rain") |
1542 | + )))).WillOnce(Return(true)); |
1543 | + EXPECT_CALL(reply, push(Matcher<sc::CategorisedResult const&>(AllOf( |
1544 | + ResultProp("title", "17.4°C to 15.4°C"), |
1545 | + ResultProp("art", "http://openweathermap.org/img/w/10d.png"), |
1546 | + ResultProp("subtitle", "heavy intensity rain") |
1547 | + )))).WillOnce(Return(true)); |
1548 | + EXPECT_CALL(reply, push(Matcher<sc::CategorisedResult const&>(AllOf( |
1549 | + ResultProp("title", "18.4°C to 16.2°C"), |
1550 | + ResultProp("art", "http://openweathermap.org/img/w/10d.png"), |
1551 | + ResultProp("subtitle", "moderate rain") |
1552 | + )))).WillOnce(Return(true)); |
1553 | + EXPECT_CALL(reply, push(Matcher<sc::CategorisedResult const&>(AllOf( |
1554 | + ResultProp("title", "19°C to 16.7°C"), |
1555 | + ResultProp("art", "http://openweathermap.org/img/w/10d.png"), |
1556 | + ResultProp("subtitle", "light rain") |
1557 | + )))).WillOnce(Return(true)); |
1558 | + |
1559 | + sc::SearchReplyProxy reply_proxy(&reply, [](sc::SearchReply*) {}); // note: this is a std::shared_ptr with empty deleter |
1560 | + sc::SearchMetadata meta_data("en_EN", "phone"); |
1561 | + |
1562 | + // Create a query object |
1563 | + auto search_query = scope->search(query, meta_data); |
1564 | + ASSERT_NE(nullptr, search_query); |
1565 | + |
1566 | + // Run the search |
1567 | + search_query->run(reply_proxy); |
1568 | + |
1569 | + // Google Mock will make assertions when the mocks are destructed. |
1570 | +} |
1571 | + |
1572 | +TEST_F(TestScope, search) { |
1573 | + const sc::CategoryRenderer renderer; |
1574 | + NiceMock<sct::MockSearchReply> reply; |
1575 | + |
1576 | + // Build a query with a non-empty search string |
1577 | + sc::CannedQuery query(SCOPE_NAME, "Manchester,uk", ""); |
1578 | + |
1579 | + // Expect the current weather category |
1580 | + EXPECT_CALL(reply, register_category("current", "Manchester, GB", "", _)).Times(1) |
1581 | + .WillOnce(Return(make_shared<sct::Category>("current", "Manchester, GB", "", renderer))); |
1582 | + |
1583 | + // With one result |
1584 | + EXPECT_CALL(reply, push(Matcher<sc::CategorisedResult const&>(AllOf( |
1585 | + ResultProp("title", "17.4°C"), |
1586 | + ResultProp("art", "http://openweathermap.org/img/w/03d.png"), |
1587 | + ResultProp("subtitle", "scattered clouds") |
1588 | + )))).WillOnce( |
1589 | + Return(true)); |
1590 | + |
1591 | + // Expect the forecast category |
1592 | + EXPECT_CALL(reply, register_category("forecast", "7 day forecast", "", _)).Times(1) |
1593 | + .WillOnce(Return(make_shared<sct::Category>("forecast", "7 day forecast", "", renderer))); |
1594 | + |
1595 | + // With seven results |
1596 | + EXPECT_CALL(reply, push(Matcher<sc::CategorisedResult const&>(AllOf( |
1597 | + ResultProp("title", "18.8°C to 12°C"), |
1598 | + ResultProp("art", "http://openweathermap.org/img/w/01d.png"), |
1599 | + ResultProp("subtitle", "sky is clear") |
1600 | + )))).WillOnce(Return(true)); |
1601 | + EXPECT_CALL(reply, push(Matcher<sc::CategorisedResult const&>(AllOf( |
1602 | + ResultProp("title", "18.6°C to 12.3°C"), |
1603 | + ResultProp("art", "http://openweathermap.org/img/w/10d.png"), |
1604 | + ResultProp("subtitle", "moderate rain") |
1605 | + )))).WillOnce(Return(true)); |
1606 | + EXPECT_CALL(reply, push(Matcher<sc::CategorisedResult const&>(AllOf( |
1607 | + ResultProp("title", "17.1°C to 10.8°C"), |
1608 | + ResultProp("art", "http://openweathermap.org/img/w/04d.png"), |
1609 | + ResultProp("subtitle", "broken clouds") |
1610 | + )))).WillOnce(Return(true)); |
1611 | + EXPECT_CALL(reply, push(Matcher<sc::CategorisedResult const&>(AllOf( |
1612 | + ResultProp("title", "16°C to 12.2°C"), |
1613 | + ResultProp("art", "http://openweathermap.org/img/w/10d.png"), |
1614 | + ResultProp("subtitle", "moderate rain") |
1615 | + )))).WillOnce(Return(true)); |
1616 | + EXPECT_CALL(reply, push(Matcher<sc::CategorisedResult const&>(AllOf( |
1617 | + ResultProp("title", "15.7°C to 13°C"), |
1618 | + ResultProp("art", "http://openweathermap.org/img/w/10d.png"), |
1619 | + ResultProp("subtitle", "light rain") |
1620 | + )))).WillOnce(Return(true)); |
1621 | + EXPECT_CALL(reply, push(Matcher<sc::CategorisedResult const&>(AllOf( |
1622 | + ResultProp("title", "17.6°C to 14.1°C"), |
1623 | + ResultProp("art", "http://openweathermap.org/img/w/10d.png"), |
1624 | + ResultProp("subtitle", "moderate rain") |
1625 | + )))).WillOnce(Return(true)); |
1626 | + EXPECT_CALL(reply, push(Matcher<sc::CategorisedResult const&>(AllOf( |
1627 | + ResultProp("title", "15.5°C to 13.4°C"), |
1628 | + ResultProp("art", "http://openweathermap.org/img/w/10d.png"), |
1629 | + ResultProp("subtitle", "moderate rain") |
1630 | + )))).WillOnce(Return(true)); |
1631 | + |
1632 | + sc::SearchReplyProxy reply_proxy(&reply, [](sc::SearchReply*) {}); // note: this is a std::shared_ptr with empty deleter |
1633 | + sc::SearchMetadata meta_data("en_EN", "phone"); |
1634 | + |
1635 | + // Create a query object |
1636 | + auto search_query = scope->search(query, meta_data); |
1637 | + ASSERT_NE(nullptr, search_query); |
1638 | + |
1639 | + // Run the search |
1640 | + search_query->run(reply_proxy); |
1641 | + |
1642 | + // Google Mock will make assertions when the mocks are destructed. |
1643 | +} |
1644 | + |
1645 | +} // namespace |
1646 | |
1647 | === modified file 'share/qtcreator/templates/wizards/ubuntu/scope/wizard.xml' |
1648 | --- share/qtcreator/templates/wizards/ubuntu/scope/wizard.xml 2014-08-18 12:29:43 +0000 |
1649 | +++ share/qtcreator/templates/wizards/ubuntu/scope/wizard.xml 2014-09-03 15:09:42 +0000 |
1650 | @@ -2,28 +2,46 @@ |
1651 | <wizard version="1" kind="project" firstpage="10" id="UbuntuUnityScope" category="A.UbuntuProject" |
1652 | platformIndependent="true" |
1653 | class="ubuntu-project-cmake" |
1654 | - featuresRequired="" |
1655 | + featuresRequired="" |
1656 | > |
1657 | <icon>../share/ubuntu.png</icon> |
1658 | <description>A simple C++ based Unity Scope</description> |
1659 | <displayname>Unity Scope</displayname> |
1660 | <displaycategory>Ubuntu</displaycategory> |
1661 | <files> |
1662 | - <file source="data/displayName.ini.in" target="data/%ClickDomain:l%.%ProjectName:l%_%ClickHookName:l%.ini.in" openeditor="false"/> |
1663 | - <file source="data/CMakeLists.txt" target="data/CMakeLists.txt" openeditor="false"/> |
1664 | - <file source="displayName.apparmor" target="%ClickHookName:l%.apparmor" openeditor="false"/> |
1665 | - <file source="test/simpletest.cpp" target="test/simpletest.cpp" openeditor="false"/> |
1666 | - <file source="test/CMakeLists.txt" target="test/CMakeLists.txt" openeditor="false"/> |
1667 | - <file source="manifest.json" target="manifest.json" openeditor="true"/> |
1668 | - <file source="src/displayName-preview.h" target="src/%ClickHookName:l%-preview.h" openeditor="false"/> |
1669 | - <file source="src/displayName-query.h" target="src/%ClickHookName:l%-query.h" openeditor="false"/> |
1670 | - <file source="src/displayName-preview.cpp" target="src/%ClickHookName:l%-preview.cpp" openeditor="false"/> |
1671 | - <file source="src/displayName-query.cpp" target="src/%ClickHookName:l%-query.cpp" openeditor="false"/> |
1672 | - <file source="src/CMakeLists.txt" target="src/CMakeLists.txt" openeditor="false"/> |
1673 | - <file source="src/displayName-scope.h" target="src/%ClickHookName:l%-scope.h" openeditor="false"/> |
1674 | - <file source="src/displayName-scope.cpp" target="src/%ClickHookName:l%-scope.cpp" openeditor="false"/> |
1675 | - <file source="readme.txt" target="readme.txt" openeditor="true"/> |
1676 | - <file source="CMakeLists.txt" target="CMakeLists.txt" openeditor="true" openproject="true"/> |
1677 | + <file source="cmake/FindGMock.cmake"/> |
1678 | + |
1679 | + <file source="data/CMakeLists.txt"/> |
1680 | + <file source="data/displayName.ini" target="data/%ClickDomain:l%.%ProjectName:l%_%ClickHookName:l%.ini"/> |
1681 | + <file source="data/icon.png" binary="true"/> |
1682 | + <file source="data/logo.png" binary="true"/> |
1683 | + <file source="data/screenshot.png" binary="true"/> |
1684 | + |
1685 | + <file source="include/api/config.h"/> |
1686 | + <file source="include/api/client.h"/> |
1687 | + <file source="include/scope/preview.h"/> |
1688 | + <file source="include/scope/query.h"/> |
1689 | + <file source="include/scope/scope.h"/> |
1690 | + |
1691 | + <file source="src/CMakeLists.txt"/> |
1692 | + <file source="src/api/client.cpp"/> |
1693 | + <file source="src/scope/query.cpp"/> |
1694 | + <file source="src/scope/scope.cpp" openeditor="true"/> |
1695 | + <file source="src/scope/preview.cpp"/> |
1696 | + |
1697 | + <file source="tests/server/forecast/daily/Manchester,uk.json"/> |
1698 | + <file source="tests/server/forecast/daily/London,uk.json"/> |
1699 | + <file source="tests/server/weather/Manchester,uk.json"/> |
1700 | + <file source="tests/server/weather/London,uk.json"/> |
1701 | + <file source="tests/server/server.py"/> |
1702 | + <file source="tests/CMakeLists.txt"/> |
1703 | + <file source="tests/unit/CMakeLists.txt"/> |
1704 | + <file source="tests/unit/scope/test-scope.cpp"/> |
1705 | + |
1706 | + <file source="CMakeLists.txt" openproject="true"/> |
1707 | + <file source="displayName.apparmor" target="%ClickHookName:l%.apparmor"/> |
1708 | + <file source="manifest.json" openeditor="true"/> |
1709 | + <file source="readme.txt"/> |
1710 | </files> |
1711 | |
1712 | <!-- Create a 2nd wizard page with click package parameters --> |
PASSED: Continuous integration, rev:252 jenkins. qa.ubuntu. com/job/ qtcreator- plugin- ubuntu- ci/406/ jenkins. qa.ubuntu. com/job/ qtcreator- plugin- ubuntu- utopic- amd64-ci/ 174 jenkins. qa.ubuntu. com/job/ qtcreator- plugin- ubuntu- utopic- armhf-ci/ 174
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/qtcreator- plugin- ubuntu- ci/406/ rebuild
http://