Merge lp:~alecu/unity-scope-click/uninstall-scopes into lp:unity-scope-click/devel
- uninstall-scopes
- Merge into devel
Status: | Superseded |
---|---|
Proposed branch: | lp:~alecu/unity-scope-click/uninstall-scopes |
Merge into: | lp:unity-scope-click/devel |
Diff against target: |
1816 lines (+1007/-192) 28 files modified
CMakeLists.txt (+10/-5) data/CMakeLists.txt (+41/-19) data/clickscope.ini.in.in (+8/-0) data/com.canonical.scopes.clickstore.ini.in.in (+3/-3) libclickscope/click/interface.cpp (+55/-21) libclickscope/click/interface.h (+7/-4) libclickscope/click/preview.cpp (+32/-4) libclickscope/click/preview.h (+7/-0) libclickscope/click/scope_activation.cpp (+31/-0) libclickscope/click/scope_activation.h (+13/-0) libclickscope/tests/test_interface.cpp (+80/-18) po/POTFILES.in (+5/-3) scope/CMakeLists.txt (+3/-2) scope/clickapps/CMakeLists.txt (+37/-0) scope/clickapps/apps-query.cpp (+218/-0) scope/clickapps/apps-query.h (+82/-0) scope/clickapps/apps-scope.cpp (+158/-0) scope/clickapps/apps-scope.h (+71/-0) scope/clickstore/CMakeLists.txt (+8/-7) scope/clickstore/store-query.cpp (+30/-56) scope/clickstore/store-query.h (+7/-8) scope/clickstore/store-scope.cpp (+2/-2) scope/tests/CMakeLists.txt (+1/-1) scope/tests/click_interface_tool/CMakeLists.txt (+1/-1) scope/tests/click_interface_tool/click_interface_tool.cpp (+2/-2) scope/tests/download_manager_tool/CMakeLists.txt (+1/-1) scope/tests/integration/CMakeLists.txt (+1/-1) scope/tests/test_query.cpp (+93/-34) |
To merge this branch: | bzr merge lp:~alecu/unity-scope-click/uninstall-scopes |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
PS Jenkins bot (community) | continuous-integration | Approve | |
Unity Team | Pending | ||
Review via email: mp+221806@code.launchpad.net |
This proposal has been superseded by a proposal from 2014-06-06.
Commit message
Allow installed packages in the Available category
Description of the change
PS Jenkins bot (ps-jenkins) wrote : | # |
- 282. By Alejandro J. Cura
-
Include subtitle with price or Installed
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:282
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 283. By Alejandro J. Cura
-
Use the proper list of installed packages
- 284. By Alejandro J. Cura
-
Merged with lp:~stolowski/unity-scope-click/two-scopes
- 285. By Alejandro J. Cura
-
Fix broken tests after the merge
- 286. By Alejandro J. Cura
-
Removing fit, changing aspect-ratio to 1.13
- 287. By Alejandro J. Cura
-
Merged from lp:~stolowski/unity-scope-click/two-scopes
- 288. By Alejandro J. Cura
-
Test for get_installed_
packages async->sync method - 289. By Alejandro J. Cura
-
Use a typedef for PackageNames
- 290. By Alejandro J. Cura
-
After talking with pawel, realized keeping this was a mixup from the merge
- 291. By Alejandro J. Cura
-
Make new strings translatable
- 292. By Alejandro J. Cura
-
Better reporting of errors when parsing the output of 'click list'
- 293. By Alejandro J. Cura
-
Simplified parsing of click list lines
- 294. By Alejandro J. Cura
-
Use a set of Packages instead of the Packages' names
- 295. By Alejandro J. Cura
-
Store the installed version in the scope result
- 296. By Alejandro J. Cura
-
Allow searching installed scopes
- 297. By Alejandro J. Cura
-
Use the package name for the scope id
- 298. By Alejandro J. Cura
-
merged with devel
Unmerged revisions
- 298. By Alejandro J. Cura
-
merged with devel
- 297. By Alejandro J. Cura
-
Use the package name for the scope id
- 296. By Alejandro J. Cura
-
Allow searching installed scopes
- 295. By Alejandro J. Cura
-
Store the installed version in the scope result
- 294. By Alejandro J. Cura
-
Use a set of Packages instead of the Packages' names
- 293. By Alejandro J. Cura
-
Simplified parsing of click list lines
- 292. By Alejandro J. Cura
-
Better reporting of errors when parsing the output of 'click list'
- 291. By Alejandro J. Cura
-
Make new strings translatable
- 290. By Alejandro J. Cura
-
After talking with pawel, realized keeping this was a mixup from the merge
- 289. By Alejandro J. Cura
-
Use a typedef for PackageNames
Preview Diff
1 | === modified file 'CMakeLists.txt' |
2 | --- CMakeLists.txt 2014-05-23 18:47:34 +0000 |
3 | +++ CMakeLists.txt 2014-06-06 00:43:07 +0000 |
4 | @@ -14,8 +14,10 @@ |
5 | |
6 | include(GNUInstallDirs) |
7 | |
8 | -set(SCOPE_LIB_DIR ${CMAKE_INSTALL_FULL_LIBDIR}/unity-scopes/clickscope/) |
9 | -set(SCOPE_DATA_DIR ${CMAKE_INSTALL_FULL_DATADIR}/unity/scopes/clickscope/) |
10 | +set(STORE_LIB_DIR ${CMAKE_INSTALL_FULL_LIBDIR}/unity-scopes/clickstore/) |
11 | +set(STORE_DATA_DIR ${CMAKE_INSTALL_FULL_DATADIR}/unity/scopes/clickstore/) |
12 | +set(APPS_LIB_DIR ${CMAKE_INSTALL_FULL_LIBDIR}/unity-scopes/clickapps/) |
13 | +set(APPS_DATA_DIR ${CMAKE_INSTALL_FULL_DATADIR}/unity/scopes/clickapps/) |
14 | |
15 | include(FindPkgConfig) |
16 | |
17 | @@ -32,8 +34,11 @@ |
18 | SET (SCOPE_LIB_VERSION 0.2.0) |
19 | SET (SCOPE_LIB_SOVERSION 0) |
20 | SET (SCOPE_LIB_API_VERSION 2.0) |
21 | -SET (SCOPE_LIB_UNVERSIONED clickscope) |
22 | -SET (SCOPE_LIB_NAME ${SCOPE_LIB_UNVERSIONED}-${SCOPE_LIB_API_VERSION}) |
23 | +SET (STORE_LIB_UNVERSIONED com.canonical.scopes.clickstore) |
24 | +SET (SCOPE_LIB_NAME clickscope) |
25 | +SET (STORE_LIB_NAME ${STORE_LIB_UNVERSIONED}-${SCOPE_LIB_API_VERSION}) |
26 | +SET (APPS_LIB_UNVERSIONED scope) |
27 | +SET (APPS_LIB_NAME ${APPS_LIB_UNVERSIONED}-${SCOPE_LIB_API_VERSION}) |
28 | |
29 | # Build with system gmock and embedded gtest |
30 | set (GMOCK_INCLUDE_DIR "/usr/include/gmock/include" CACHE PATH "gmock source include directory") |
31 | @@ -108,4 +113,4 @@ |
32 | |
33 | add_custom_target (check-leaks |
34 | DEPENDS test-leaks |
35 | -) |
36 | \ No newline at end of file |
37 | +) |
38 | |
39 | === modified file 'data/CMakeLists.txt' |
40 | --- data/CMakeLists.txt 2014-04-29 18:42:40 +0000 |
41 | +++ data/CMakeLists.txt 2014-06-06 00:43:07 +0000 |
42 | @@ -1,21 +1,43 @@ |
43 | find_program(INTLTOOL_MERGE intltool-merge) |
44 | -set(SCOPE_INI_TARGET clickscope.ini) |
45 | - |
46 | -configure_file( |
47 | - ${SCOPE_INI_TARGET}.in.in |
48 | - ${SCOPE_INI_TARGET}.in |
49 | -) |
50 | - |
51 | -add_custom_target(${SCOPE_INI_TARGET} ALL |
52 | - COMMENT "Merging translations into ${SCOPE_INI_TARGET}" |
53 | - COMMAND LC_ALL=C ${INTLTOOL_MERGE} -d -u ${CMAKE_SOURCE_DIR}/po ${SCOPE_INI_TARGET}.in ${SCOPE_INI_TARGET} >/dev/null |
54 | -) |
55 | - |
56 | -install( |
57 | - FILES clickscope-screenshot.jpg apps-scope.svg |
58 | - DESTINATION "${SCOPE_DATA_DIR}" |
59 | -) |
60 | -install( |
61 | - FILES "${CMAKE_CURRENT_BINARY_DIR}/${SCOPE_INI_TARGET}" |
62 | - DESTINATION "${SCOPE_LIB_DIR}" |
63 | +set(STORE_INI_TARGET com.canonical.scopes.clickstore.ini) |
64 | +set(APPS_INI_TARGET clickscope.ini) |
65 | + |
66 | +configure_file( |
67 | + ${STORE_INI_TARGET}.in.in |
68 | + ${STORE_INI_TARGET}.in |
69 | +) |
70 | + |
71 | +configure_file( |
72 | + ${APPS_INI_TARGET}.in.in |
73 | + ${APPS_INI_TARGET}.in |
74 | +) |
75 | + |
76 | +add_custom_target(${STORE_INI_TARGET} ALL |
77 | + COMMENT "Merging translations into ${STORE_INI_TARGET}" |
78 | + COMMAND LC_ALL=C ${INTLTOOL_MERGE} -d -u ${CMAKE_SOURCE_DIR}/po ${STORE_INI_TARGET}.in ${STORE_INI_TARGET} >/dev/null |
79 | +) |
80 | + |
81 | +add_custom_target(${APPS_INI_TARGET} ALL |
82 | + COMMENT "Merging translations into ${APPS_INI_TARGET}" |
83 | + COMMAND LC_ALL=C ${INTLTOOL_MERGE} -d -u ${CMAKE_SOURCE_DIR}/po ${APPS_INI_TARGET}.in ${APPS_INI_TARGET} >/dev/null |
84 | +) |
85 | + |
86 | +install( |
87 | + FILES clickscope-screenshot.jpg apps-scope.svg |
88 | + DESTINATION "${STORE_DATA_DIR}" |
89 | +) |
90 | + |
91 | +install( |
92 | + FILES clickscope-screenshot.jpg apps-scope.svg |
93 | + DESTINATION "${APPS_DATA_DIR}" |
94 | +) |
95 | + |
96 | +install( |
97 | + FILES "${CMAKE_CURRENT_BINARY_DIR}/${STORE_INI_TARGET}" |
98 | + DESTINATION "${STORE_LIB_DIR}" |
99 | +) |
100 | + |
101 | +install( |
102 | + FILES "${CMAKE_CURRENT_BINARY_DIR}/${APPS_INI_TARGET}" |
103 | + DESTINATION "${APPS_LIB_DIR}" |
104 | ) |
105 | |
106 | === added file 'data/clickscope.ini.in.in' |
107 | --- data/clickscope.ini.in.in 1970-01-01 00:00:00 +0000 |
108 | +++ data/clickscope.ini.in.in 2014-06-06 00:43:07 +0000 |
109 | @@ -0,0 +1,8 @@ |
110 | +[ScopeConfig] |
111 | +_DisplayName=Apps |
112 | +_Description=Scope for searching the installed click apps |
113 | +Author=Canonical Ltd. |
114 | +Art=@APPS_DATA_DIR@/clickscope-screenshot.jpg |
115 | +Icon=@APPS_DATA_DIR@/apps-scope.svg |
116 | +SearchHint=clickscope.SearchHint |
117 | +HotKey=clickscope.HotKey |
118 | |
119 | === renamed file 'data/clickscope.ini.in.in' => 'data/com.canonical.scopes.clickstore.ini.in.in' |
120 | --- data/clickscope.ini.in.in 2014-04-29 18:42:40 +0000 |
121 | +++ data/com.canonical.scopes.clickstore.ini.in.in 2014-06-06 00:43:07 +0000 |
122 | @@ -1,8 +1,8 @@ |
123 | [ScopeConfig] |
124 | -_DisplayName=Apps |
125 | +_DisplayName=Ubuntu Store |
126 | _Description=Scope for searching the click app store |
127 | Author=Canonical Ltd. |
128 | -Art=@SCOPE_DATA_DIR@/clickscope-screenshot.jpg |
129 | -Icon=@SCOPE_DATA_DIR@/apps-scope.svg |
130 | +Art=@STORE_DATA_DIR@/clickscope-screenshot.jpg |
131 | +Icon=@STORE_DATA_DIR@/apps-scope.svg |
132 | SearchHint=clickscope.SearchHint |
133 | HotKey=clickscope.HotKey |
134 | |
135 | === modified file 'libclickscope/click/interface.cpp' |
136 | --- libclickscope/click/interface.cpp 2014-05-26 14:02:45 +0000 |
137 | +++ libclickscope/click/interface.cpp 2014-06-06 00:43:07 +0000 |
138 | @@ -217,11 +217,6 @@ |
139 | }; |
140 | |
141 | keyFileLocator->enumerateKeyFilesForInstalledApplications(enumerator); |
142 | - // Sort applications so that newest come first. |
143 | - std::sort(result.begin(), result.end(), [](const Application& a, |
144 | - const Application& b) { |
145 | - return a.installed_time > b.installed_time; |
146 | - }); |
147 | return result; |
148 | } |
149 | |
150 | @@ -321,7 +316,7 @@ |
151 | return manifest; |
152 | } |
153 | |
154 | -void Interface::get_manifests(std::function<void(ManifestList, ManifestError)> callback) |
155 | +void Interface::get_manifests(std::function<void(ManifestList, InterfaceError)> callback) |
156 | { |
157 | std::string command = "click list --manifest"; |
158 | qDebug() << "Running command:" << command.c_str(); |
159 | @@ -329,18 +324,57 @@ |
160 | if (code == 0) { |
161 | try { |
162 | ManifestList manifests = manifest_list_from_json(stdout_data); |
163 | - callback(manifests, ManifestError::NoError); |
164 | - } catch (...) { |
165 | - callback(ManifestList(), ManifestError::ParseError); |
166 | - } |
167 | - } else { |
168 | - callback(ManifestList(), ManifestError::CallError); |
169 | + callback(manifests, InterfaceError::NoError); |
170 | + } catch (...) { |
171 | + callback(ManifestList(), InterfaceError::ParseError); |
172 | + } |
173 | + } else { |
174 | + callback(ManifestList(), InterfaceError::CallError); |
175 | + } |
176 | + }); |
177 | +} |
178 | + |
179 | +PackageNames package_names_from_stdout(std::string stdout_data) |
180 | +{ |
181 | + PackageNames package_names; |
182 | + const char newline = '\n'; |
183 | + const char tab = '\t'; |
184 | + |
185 | + size_t linestart = 0, tabpos; |
186 | + size_t eof = stdout_data.length(); |
187 | + |
188 | + while (linestart < eof) { |
189 | + tabpos = stdout_data.find_first_of(tab, linestart); |
190 | + if (tabpos == std::string::npos) { |
191 | + throw std::runtime_error("No tab in click list line"); |
192 | + } |
193 | + package_names.insert(stdout_data.substr(linestart, tabpos-linestart)); |
194 | + linestart = stdout_data.find_first_of(newline, tabpos) + 1; |
195 | + } |
196 | + |
197 | + return package_names; |
198 | +} |
199 | + |
200 | +void Interface::get_installed_packagenames(std::function<void(PackageNames, InterfaceError)> callback) |
201 | +{ |
202 | + std::string command = "click list"; |
203 | + qDebug() << "Running command:" << command.c_str(); |
204 | + run_process(command, [callback](int code, const std::string& stdout_data, const std::string&) { |
205 | + if (code == 0) { |
206 | + try { |
207 | + PackageNames package_names = package_names_from_stdout(stdout_data); |
208 | + callback(package_names, InterfaceError::NoError); |
209 | + } catch (...) { |
210 | + callback({}, InterfaceError::ParseError); |
211 | + } |
212 | + } else { |
213 | + callback({}, InterfaceError::CallError); |
214 | } |
215 | }); |
216 | } |
217 | |
218 | void Interface::get_manifest_for_app(const std::string &app_id, |
219 | - std::function<void(Manifest, ManifestError)> callback) |
220 | + std::function<void(Manifest, InterfaceError)> callback) |
221 | { |
222 | std::string command = "click info " + app_id; |
223 | qDebug() << "Running command:" << command.c_str(); |
224 | @@ -348,23 +382,23 @@ |
225 | if (code == 0) { |
226 | try { |
227 | Manifest manifest = manifest_from_json(stdout_data); |
228 | - callback(manifest, ManifestError::NoError); |
229 | + callback(manifest, InterfaceError::NoError); |
230 | } catch (...) { |
231 | - callback(Manifest(), ManifestError::ParseError); |
232 | + callback(Manifest(), InterfaceError::ParseError); |
233 | } |
234 | } else { |
235 | - callback(Manifest(), ManifestError::CallError); |
236 | + callback(Manifest(), InterfaceError::CallError); |
237 | } |
238 | }); |
239 | } |
240 | |
241 | void Interface::get_dotdesktop_filename(const std::string &app_id, |
242 | - std::function<void(std::string, ManifestError)> callback) |
243 | + std::function<void(std::string, InterfaceError)> callback) |
244 | { |
245 | - get_manifest_for_app(app_id, [app_id, callback] (Manifest manifest, ManifestError error) { |
246 | + get_manifest_for_app(app_id, [app_id, callback] (Manifest manifest, InterfaceError error) { |
247 | qDebug() << "in get_dotdesktop_filename callback"; |
248 | |
249 | - if (error != ManifestError::NoError){ |
250 | + if (error != InterfaceError::NoError){ |
251 | callback(std::string("Internal Error"), error); |
252 | return; |
253 | } |
254 | @@ -372,10 +406,10 @@ |
255 | |
256 | if (!manifest.name.empty()) { |
257 | std::string ddstr = manifest.name + "_" + manifest.first_app_name + "_" + manifest.version + ".desktop"; |
258 | - callback(ddstr, ManifestError::NoError); |
259 | + callback(ddstr, InterfaceError::NoError); |
260 | } else { |
261 | qCritical() << "Warning: no manifest found for " << app_id.c_str(); |
262 | - callback(std::string("Not found"), ManifestError::CallError); |
263 | + callback(std::string("Not found"), InterfaceError::CallError); |
264 | } |
265 | }); |
266 | } |
267 | |
268 | === modified file 'libclickscope/click/interface.h' |
269 | --- libclickscope/click/interface.h 2014-05-26 14:02:45 +0000 |
270 | +++ libclickscope/click/interface.h 2014-06-06 00:43:07 +0000 |
271 | @@ -62,12 +62,14 @@ |
272 | bool removable = false; |
273 | }; |
274 | |
275 | -enum class ManifestError {NoError, CallError, ParseError}; |
276 | +enum class InterfaceError {NoError, CallError, ParseError}; |
277 | typedef std::list<Manifest> ManifestList; |
278 | |
279 | ManifestList manifest_list_from_json(const std::string& json); |
280 | Manifest manifest_from_json(const std::string& json); |
281 | |
282 | +typedef std::unordered_set<std::string> PackageNames; |
283 | + |
284 | class Interface |
285 | { |
286 | public: |
287 | @@ -87,10 +89,11 @@ |
288 | |
289 | static bool is_icon_identifier(const std::string &icon_id); |
290 | static std::string add_theme_scheme(const std::string &filename); |
291 | - virtual void get_manifests(std::function<void(ManifestList, ManifestError)> callback); |
292 | - virtual void get_manifest_for_app(const std::string &app_id, std::function<void(Manifest, ManifestError)> callback); |
293 | + virtual void get_manifests(std::function<void(ManifestList, InterfaceError)> callback); |
294 | + virtual void get_installed_packagenames(std::function<void(PackageNames, InterfaceError)> callback); |
295 | + virtual void get_manifest_for_app(const std::string &app_id, std::function<void(Manifest, InterfaceError)> callback); |
296 | virtual void get_dotdesktop_filename(const std::string &app_id, |
297 | - std::function<void(std::string filename, ManifestError)> callback); |
298 | + std::function<void(std::string filename, InterfaceError)> callback); |
299 | constexpr static const char* ENV_SHOW_DESKTOP_APPS {"CLICK_SCOPE_SHOW_DESKTOP_APPS"}; |
300 | virtual bool is_visible_app(const unity::util::IniParser& keyFile); |
301 | virtual bool show_desktop_apps(); |
302 | |
303 | === modified file 'libclickscope/click/preview.cpp' |
304 | --- libclickscope/click/preview.cpp 2014-05-26 14:02:45 +0000 |
305 | +++ libclickscope/click/preview.cpp 2014-06-06 00:43:07 +0000 |
306 | @@ -100,6 +100,10 @@ |
307 | } |
308 | } else { |
309 | // metadata.scope_data() is Null, so we return an appropriate "default" preview: |
310 | + if (result.uri().find("scope://") == 0) |
311 | + { |
312 | + return new InstalledScopePreview(result); |
313 | + } |
314 | if (result["installed"].get_bool() == true) { |
315 | return new InstalledPreview(result, metadata, client); |
316 | } else { |
317 | @@ -435,7 +439,7 @@ |
318 | if (!app_name.empty()) { |
319 | qt::core::world::enter_with_task([&]() { |
320 | click::Interface().get_manifest_for_app(app_name, |
321 | - [&](Manifest manifest, ManifestError error) { |
322 | + [&](Manifest manifest, InterfaceError error) { |
323 | qDebug() << "Got manifest for:" << app_name.c_str(); |
324 | removable = manifest.removable; |
325 | |
326 | @@ -443,7 +447,7 @@ |
327 | review.package_name = manifest.name; |
328 | review.package_version = manifest.version; |
329 | |
330 | - if (error != click::ManifestError::NoError) { |
331 | + if (error != click::InterfaceError::NoError) { |
332 | qDebug() << "There was an error getting the manifest for:" << app_name.c_str(); |
333 | } |
334 | manifest_promise.set_value(true); |
335 | @@ -532,9 +536,9 @@ |
336 | auto ft = qt::core::world::enter_with_task([this, name, callback] () |
337 | { |
338 | click::Interface().get_dotdesktop_filename(name, |
339 | - [callback] (std::string val, click::ManifestError error) { |
340 | + [callback] (std::string val, click::InterfaceError error) { |
341 | std::string uri; |
342 | - if (error == click::ManifestError::NoError) { |
343 | + if (error == click::InterfaceError::NoError) { |
344 | uri = "application:///" + val; |
345 | } |
346 | callback(uri); |
347 | @@ -547,6 +551,30 @@ |
348 | } |
349 | } |
350 | |
351 | +// class InstalledScopePreview |
352 | +// this is a temporary fallback preview to get into the Store scope, the proper |
353 | +// requires 'store' category to be treated special (like 'local') in unity8 shell. |
354 | + |
355 | +InstalledScopePreview::InstalledScopePreview(const unity::scopes::Result& result) |
356 | + : PreviewStrategy(result) |
357 | +{ |
358 | +} |
359 | + |
360 | +void InstalledScopePreview::run(unity::scopes::PreviewReplyProxy const& reply) |
361 | +{ |
362 | + scopes::PreviewWidget actions("actions", "actions"); |
363 | + { |
364 | + scopes::VariantBuilder builder; |
365 | + builder.add_tuple({ |
366 | + {"id", scopes::Variant("search")}, |
367 | + {"uri", scopes::Variant(result.uri())}, |
368 | + {"label", scopes::Variant(_("Search"))} |
369 | + }); |
370 | + actions.add_attribute_value("actions", builder.end()); |
371 | + } |
372 | + |
373 | + reply->push({actions}); |
374 | +} |
375 | |
376 | // class PurchasingPreview |
377 | |
378 | |
379 | === modified file 'libclickscope/click/preview.h' |
380 | --- libclickscope/click/preview.h 2014-05-26 14:02:45 +0000 |
381 | +++ libclickscope/click/preview.h 2014-06-06 00:43:07 +0000 |
382 | @@ -172,6 +172,13 @@ |
383 | scopes::ActionMetadata metadata; |
384 | }; |
385 | |
386 | +class InstalledScopePreview : public PreviewStrategy |
387 | +{ |
388 | +public: |
389 | + InstalledScopePreview(const unity::scopes::Result& result); |
390 | + void run(unity::scopes::PreviewReplyProxy const& reply) override; |
391 | +}; |
392 | + |
393 | class PurchasingPreview : public PreviewStrategy |
394 | { |
395 | public: |
396 | |
397 | === modified file 'libclickscope/click/scope_activation.cpp' |
398 | --- libclickscope/click/scope_activation.cpp 2014-05-26 14:02:45 +0000 |
399 | +++ libclickscope/click/scope_activation.cpp 2014-06-06 00:43:07 +0000 |
400 | @@ -28,6 +28,9 @@ |
401 | */ |
402 | |
403 | #include "scope_activation.h" |
404 | +#include <click/package.h> |
405 | +#include <click/interface.h> |
406 | +#include <click/qtbridge.h> |
407 | #include <unity/scopes/ActivationResponse.h> |
408 | |
409 | unity::scopes::ActivationResponse click::ScopeActivation::activate() |
410 | @@ -46,3 +49,31 @@ |
411 | { |
412 | hints_[key] = value; |
413 | } |
414 | + |
415 | +click::PerformUninstallAction::PerformUninstallAction(const unity::scopes::Result& result, const unity::scopes::ActivationResponse& response) |
416 | + : result(result), |
417 | + response(response) |
418 | +{ |
419 | +} |
420 | + |
421 | +unity::scopes::ActivationResponse click::PerformUninstallAction::activate() |
422 | +{ |
423 | + click::Package package; |
424 | + package.title = result.title(); |
425 | + package.name = result["name"].get_string(); |
426 | + package.version = result["version"].get_string(); |
427 | + qt::core::world::enter_with_task([this, package] () |
428 | + { |
429 | + click::PackageManager manager; |
430 | + manager.uninstall(package, [&](int code, std::string stderr_content) { |
431 | + if (code != 0) { |
432 | + qDebug() << "Error removing package:" << stderr_content.c_str(); |
433 | + } else { |
434 | + qDebug() << "successfully removed package"; |
435 | + |
436 | + } |
437 | + } ); |
438 | + }); |
439 | + |
440 | + return response; |
441 | +} |
442 | |
443 | === modified file 'libclickscope/click/scope_activation.h' |
444 | --- libclickscope/click/scope_activation.h 2014-05-26 14:02:45 +0000 |
445 | +++ libclickscope/click/scope_activation.h 2014-06-06 00:43:07 +0000 |
446 | @@ -31,10 +31,23 @@ |
447 | #define CLICK_SCOPE_ACTIVATION_H |
448 | |
449 | #include <unity/scopes/ActivationQueryBase.h> |
450 | +#include <unity/scopes/ActivationResponse.h> |
451 | +#include <unity/scopes/Result.h> |
452 | |
453 | namespace click |
454 | { |
455 | |
456 | +class PerformUninstallAction: public unity::scopes::ActivationQueryBase |
457 | +{ |
458 | +public: |
459 | + PerformUninstallAction(const unity::scopes::Result& result, const unity::scopes::ActivationResponse& response); |
460 | + unity::scopes::ActivationResponse activate() override; |
461 | + |
462 | +private: |
463 | + unity::scopes::Result result; |
464 | + unity::scopes::ActivationResponse response; |
465 | +}; |
466 | + |
467 | class ScopeActivation : public unity::scopes::ActivationQueryBase |
468 | { |
469 | unity::scopes::ActivationResponse activate() override; |
470 | |
471 | === modified file 'libclickscope/tests/test_interface.cpp' |
472 | --- libclickscope/tests/test_interface.cpp 2014-05-26 14:27:31 +0000 |
473 | +++ libclickscope/tests/test_interface.cpp 2014-06-06 00:43:07 +0000 |
474 | @@ -118,8 +118,9 @@ |
475 | |
476 | class ClickInterfaceTest : public ::testing::Test { |
477 | public: |
478 | - MOCK_METHOD2(manifest_callback, void(Manifest, ManifestError)); |
479 | - MOCK_METHOD2(manifests_callback, void(ManifestList, ManifestError)); |
480 | + MOCK_METHOD2(manifest_callback, void(Manifest, InterfaceError)); |
481 | + MOCK_METHOD2(manifests_callback, void(ManifestList, InterfaceError)); |
482 | + MOCK_METHOD2(installed_callback, void(PackageNames, InterfaceError)); |
483 | }; |
484 | |
485 | } |
486 | @@ -326,7 +327,7 @@ |
487 | std::string command = "click info " + FAKE_PACKAGENAME; |
488 | EXPECT_CALL(iface, run_process(command, _)). |
489 | Times(1); |
490 | - iface.get_manifest_for_app(FAKE_PACKAGENAME, [](Manifest, ManifestError){}); |
491 | + iface.get_manifest_for_app(FAKE_PACKAGENAME, [](Manifest, InterfaceError){}); |
492 | } |
493 | |
494 | TEST_F(ClickInterfaceTest, testGetManifestForAppParseError) |
495 | @@ -339,9 +340,9 @@ |
496 | const std::string&)> callback){ |
497 | callback(0, "INVALID JSON", ""); |
498 | })); |
499 | - EXPECT_CALL(*this, manifest_callback(_, ManifestError::ParseError)); |
500 | + EXPECT_CALL(*this, manifest_callback(_, InterfaceError::ParseError)); |
501 | iface.get_manifest_for_app(FAKE_PACKAGENAME, [this](Manifest manifest, |
502 | - ManifestError error){ |
503 | + InterfaceError error){ |
504 | manifest_callback(manifest, error); |
505 | }); |
506 | } |
507 | @@ -356,9 +357,9 @@ |
508 | const std::string&)> callback){ |
509 | callback(-1, "", "CRITICAL: FAIL"); |
510 | })); |
511 | - EXPECT_CALL(*this, manifest_callback(_, ManifestError::CallError)); |
512 | + EXPECT_CALL(*this, manifest_callback(_, InterfaceError::CallError)); |
513 | iface.get_manifest_for_app(FAKE_PACKAGENAME, [this](Manifest manifest, |
514 | - ManifestError error){ |
515 | + InterfaceError error){ |
516 | manifest_callback(manifest, error); |
517 | }); |
518 | } |
519 | @@ -374,8 +375,8 @@ |
520 | callback(0, FAKE_JSON_MANIFEST_REMOVABLE, ""); |
521 | })); |
522 | iface.get_manifest_for_app(FAKE_PACKAGENAME, [](Manifest manifest, |
523 | - ManifestError error){ |
524 | - ASSERT_TRUE(error == ManifestError::NoError); |
525 | + InterfaceError error){ |
526 | + ASSERT_TRUE(error == InterfaceError::NoError); |
527 | ASSERT_TRUE(manifest.removable); |
528 | }); |
529 | } |
530 | @@ -391,8 +392,8 @@ |
531 | callback(0, FAKE_JSON_MANIFEST_NONREMOVABLE, ""); |
532 | })); |
533 | iface.get_manifest_for_app(FAKE_PACKAGENAME, [](Manifest manifest, |
534 | - ManifestError error){ |
535 | - ASSERT_TRUE(error == ManifestError::NoError); |
536 | + InterfaceError error){ |
537 | + ASSERT_TRUE(error == InterfaceError::NoError); |
538 | ASSERT_FALSE(manifest.removable); |
539 | }); |
540 | } |
541 | @@ -403,7 +404,7 @@ |
542 | std::string command = "click list --manifest"; |
543 | EXPECT_CALL(iface, run_process(command, _)). |
544 | Times(1); |
545 | - iface.get_manifests([](ManifestList, ManifestError){}); |
546 | + iface.get_manifests([](ManifestList, InterfaceError){}); |
547 | } |
548 | |
549 | TEST_F(ClickInterfaceTest, testGetManifestsParseError) |
550 | @@ -416,8 +417,8 @@ |
551 | const std::string&)> callback){ |
552 | callback(0, "INVALID JSON", ""); |
553 | })); |
554 | - EXPECT_CALL(*this, manifests_callback(_, ManifestError::ParseError)); |
555 | - iface.get_manifests([this](ManifestList manifests, ManifestError error){ |
556 | + EXPECT_CALL(*this, manifests_callback(_, InterfaceError::ParseError)); |
557 | + iface.get_manifests([this](ManifestList manifests, InterfaceError error){ |
558 | manifests_callback(manifests, error); |
559 | }); |
560 | } |
561 | @@ -432,8 +433,8 @@ |
562 | const std::string&)> callback){ |
563 | callback(-1, "", "CRITICAL: FAIL"); |
564 | })); |
565 | - EXPECT_CALL(*this, manifests_callback(_, ManifestError::CallError)); |
566 | - iface.get_manifests([this](ManifestList manifests, ManifestError error){ |
567 | + EXPECT_CALL(*this, manifests_callback(_, InterfaceError::CallError)); |
568 | + iface.get_manifests([this](ManifestList manifests, InterfaceError error){ |
569 | manifests_callback(manifests, error); |
570 | }); |
571 | } |
572 | @@ -452,8 +453,69 @@ |
573 | const std::string&)> callback){ |
574 | callback(0, expected_str, ""); |
575 | })); |
576 | - iface.get_manifests([expected](ManifestList manifests, ManifestError error){ |
577 | - ASSERT_TRUE(error == ManifestError::NoError); |
578 | + iface.get_manifests([expected](ManifestList manifests, InterfaceError error){ |
579 | + ASSERT_TRUE(error == InterfaceError::NoError); |
580 | ASSERT_TRUE(manifests.size() == expected.size()); |
581 | }); |
582 | } |
583 | + |
584 | +TEST(ClickInterface, testGetInstalledPackagesCorrectCommand) |
585 | +{ |
586 | + FakeClickInterface iface; |
587 | + std::string command = "click list"; |
588 | + EXPECT_CALL(iface, run_process(command, _)). |
589 | + Times(1); |
590 | + iface.get_installed_packagenames([](PackageNames, InterfaceError){}); |
591 | +} |
592 | + |
593 | +TEST_F(ClickInterfaceTest, testGetInstalledPackagesParseError) |
594 | +{ |
595 | + FakeClickInterface iface; |
596 | + EXPECT_CALL(iface, run_process(_, _)). |
597 | + Times(1). |
598 | + WillOnce(Invoke([&](const std::string&, |
599 | + std::function<void(int, const std::string&, |
600 | + const std::string&)> callback){ |
601 | + callback(0, "valid\t\nINVALID LINE\n", ""); |
602 | + })); |
603 | + EXPECT_CALL(*this, installed_callback(_, InterfaceError::ParseError)); |
604 | + iface.get_installed_packagenames([this](PackageNames package_names, InterfaceError error){ |
605 | + installed_callback(package_names, error); |
606 | + }); |
607 | +} |
608 | + |
609 | +TEST_F(ClickInterfaceTest, testGetInstalledPackagesCommandFailed) |
610 | +{ |
611 | + FakeClickInterface iface; |
612 | + EXPECT_CALL(iface, run_process(_, _)). |
613 | + Times(1). |
614 | + WillOnce(Invoke([&](const std::string&, |
615 | + std::function<void(int, const std::string&, |
616 | + const std::string&)> callback){ |
617 | + callback(-1, "", "CRITICAL: FAIL"); |
618 | + })); |
619 | + EXPECT_CALL(*this, installed_callback(_, InterfaceError::CallError)); |
620 | + iface.get_installed_packagenames([this](PackageNames package_names, InterfaceError error){ |
621 | + installed_callback(package_names, error); |
622 | + }); |
623 | +} |
624 | + |
625 | +TEST_F(ClickInterfaceTest, testGetInstalledPackagesParsed) |
626 | +{ |
627 | + FakeClickInterface iface; |
628 | + std::string sample_stdout = "ABC\t0.1\nDEF\t0.2\n"; |
629 | + PackageNames expected{"ABC", "DEF"}; |
630 | + |
631 | + EXPECT_CALL(iface, run_process(_, _)). |
632 | + Times(1). |
633 | + WillOnce(Invoke([&](const std::string&, |
634 | + std::function<void(int, const std::string&, |
635 | + const std::string&)> callback){ |
636 | + callback(0, sample_stdout, ""); |
637 | + })); |
638 | + iface.get_installed_packagenames([expected](PackageNames package_names, InterfaceError error){ |
639 | + ASSERT_EQ(error, InterfaceError::NoError); |
640 | + ASSERT_EQ(package_names, expected); |
641 | + }); |
642 | +} |
643 | + |
644 | |
645 | === modified file 'po/POTFILES.in' |
646 | --- po/POTFILES.in 2014-04-29 18:42:40 +0000 |
647 | +++ po/POTFILES.in 2014-06-06 00:43:07 +0000 |
648 | @@ -1,3 +1,5 @@ |
649 | -[type: gettext/ini] data/clickscope.ini.in.in |
650 | -scope/click/preview.cpp |
651 | -scope/click/query.cpp |
652 | +[type: gettext/ini] data/com.canonical.scopes.clickstore.ini.in.in |
653 | +data/clickscope.ini.in.in |
654 | +libclickscope/click/preview.cpp |
655 | +scope/clickapps/apps-query.cpp |
656 | +scope/clickstore/store-query.cpp |
657 | |
658 | === modified file 'scope/CMakeLists.txt' |
659 | --- scope/CMakeLists.txt 2014-01-28 08:49:16 +0000 |
660 | +++ scope/CMakeLists.txt 2014-06-06 00:43:07 +0000 |
661 | @@ -1,2 +1,3 @@ |
662 | -add_subdirectory(click) |
663 | -add_subdirectory(tests) |
664 | \ No newline at end of file |
665 | +add_subdirectory(clickstore) |
666 | +add_subdirectory(clickapps) |
667 | +add_subdirectory(tests) |
668 | |
669 | === added directory 'scope/clickapps' |
670 | === added file 'scope/clickapps/CMakeLists.txt' |
671 | --- scope/clickapps/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
672 | +++ scope/clickapps/CMakeLists.txt 2014-06-06 00:43:07 +0000 |
673 | @@ -0,0 +1,37 @@ |
674 | +SET (CMAKE_INCLUDE_CURRENT_DIR ON) |
675 | +SET (CMAKE_AUTOMOC ON) |
676 | +find_package (Qt5Core REQUIRED) |
677 | +pkg_check_modules(JSON_CPP REQUIRED jsoncpp) |
678 | + |
679 | +add_definitions( |
680 | + -DGETTEXT_PACKAGE=\"${PROJECT_NAME}\" |
681 | + -DGETTEXT_LOCALEDIR=\"${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LOCALEDIR}\" |
682 | + -DSTORE_DATA_DIR="${STORE_DATA_DIR}" |
683 | +) |
684 | + |
685 | +add_library(${APPS_LIB_UNVERSIONED} SHARED |
686 | + apps-query.cpp |
687 | + apps-scope.cpp |
688 | +) |
689 | +set_target_properties(${APPS_LIB_UNVERSIONED} PROPERTIES PREFIX "") |
690 | + |
691 | +include_directories( |
692 | + ${CMAKE_SOURCE_DIR}/libclickscope |
693 | + ${JSON_CPP_INCLUDE_DIRS} |
694 | +) |
695 | + |
696 | +qt5_use_modules (${APPS_LIB_UNVERSIONED} Network) |
697 | + |
698 | +target_link_libraries (${APPS_LIB_UNVERSIONED} |
699 | + ${SCOPE_LIB_NAME} |
700 | + ${JSON_CPP_LDFLAGS} |
701 | + ${UNITY_SCOPES_LDFLAGS} |
702 | + ${UBUNTUONE_LDFLAGS} |
703 | + ${UBUNTU_DOWNLOAD_MANAGER_CLIENT_LDFLAGS} |
704 | + ${UBUNTU_DOWNLOAD_MANAGER_COMMON_LDFLAGS} |
705 | +) |
706 | + |
707 | +install( |
708 | + TARGETS ${APPS_LIB_UNVERSIONED} |
709 | + LIBRARY DESTINATION "${APPS_LIB_DIR}" |
710 | + ) |
711 | |
712 | === added file 'scope/clickapps/apps-query.cpp' |
713 | --- scope/clickapps/apps-query.cpp 1970-01-01 00:00:00 +0000 |
714 | +++ scope/clickapps/apps-query.cpp 2014-06-06 00:43:07 +0000 |
715 | @@ -0,0 +1,218 @@ |
716 | +/* |
717 | + * Copyright (C) 2014 Canonical Ltd. |
718 | + * |
719 | + * This program is free software: you can redistribute it and/or modify it |
720 | + * under the terms of the GNU General Public License version 3, as published |
721 | + * by the Free Software Foundation. |
722 | + * |
723 | + * This program is distributed in the hope that it will be useful, but |
724 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
725 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
726 | + * PURPOSE. See the GNU General Public License for more details. |
727 | + * |
728 | + * You should have received a copy of the GNU General Public License along |
729 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
730 | + * |
731 | + * In addition, as a special exception, the copyright holders give |
732 | + * permission to link the code of portions of this program with the |
733 | + * OpenSSL library under certain conditions as described in each |
734 | + * individual source file, and distribute linked combinations |
735 | + * including the two. |
736 | + * You must obey the GNU General Public License in all respects |
737 | + * for all of the code used other than OpenSSL. If you modify |
738 | + * file(s) with this exception, you may extend this exception to your |
739 | + * version of the file(s), but you are not obligated to do so. If you |
740 | + * do not wish to do so, delete this exception statement from your |
741 | + * version. If you delete this exception statement from all source |
742 | + * files in the program, then also delete it here. |
743 | + */ |
744 | + |
745 | +#include <click/application.h> |
746 | +#include <click/interface.h> |
747 | + |
748 | +#include <click/key_file_locator.h> |
749 | + |
750 | +#include <unity/scopes/CategoryRenderer.h> |
751 | +#include <unity/scopes/CategorisedResult.h> |
752 | +#include <unity/scopes/CannedQuery.h> |
753 | +#include <unity/scopes/SearchReply.h> |
754 | +#include <unity/scopes/SearchMetadata.h> |
755 | + |
756 | +#include <vector> |
757 | + |
758 | +#include <click/click-i18n.h> |
759 | +#include "apps-query.h" |
760 | + |
761 | +namespace |
762 | +{ |
763 | + |
764 | +std::string CATEGORY_APPS_DISPLAY = R"( |
765 | + { |
766 | + "schema-version" : 1, |
767 | + "template" : { |
768 | + "category-layout" : "grid", |
769 | + "card-size": "small" |
770 | + }, |
771 | + "components" : { |
772 | + "title" : "title", |
773 | + "art" : { |
774 | + "field": "art", |
775 | + "aspect-ratio": 1.6, |
776 | + "fill-mode": "fit" |
777 | + } |
778 | + } |
779 | + } |
780 | +)"; |
781 | + |
782 | +std::string CATEGORY_APPS_SEARCH = R"( |
783 | + { |
784 | + "schema-version" : 1, |
785 | + "template" : { |
786 | + "category-layout" : "grid", |
787 | + "card-layout" : "horizontal", |
788 | + "card-size": "large" |
789 | + }, |
790 | + "components" : { |
791 | + "title" : "title", |
792 | + "mascot" : { |
793 | + "field": "art" |
794 | + }, |
795 | + "subtitle": "publisher" |
796 | + } |
797 | + } |
798 | +)"; |
799 | + |
800 | +static const char CATEGORY_STORE[] = R"( |
801 | +{ |
802 | + "schema-version": 1, |
803 | + "template": { |
804 | + "category-layout": "grid", |
805 | + "card-size": "medium", |
806 | + "card-background": "color:///#E9E9E9" |
807 | + }, |
808 | + "components": { |
809 | + "title": "title", |
810 | + "subtitle": "author", |
811 | + "mascot": { |
812 | + "field": "art" |
813 | + }, |
814 | + "background": "background" |
815 | + } |
816 | +} |
817 | +)"; |
818 | + |
819 | + |
820 | +} |
821 | + |
822 | +void click::Query::push_local_results(scopes::SearchReplyProxy const &replyProxy, |
823 | + std::vector<click::Application> const &apps, |
824 | + std::string &categoryTemplate) |
825 | +{ |
826 | + scopes::CategoryRenderer rdr(categoryTemplate); |
827 | + auto cat = replyProxy->register_category("local", "", "", rdr); |
828 | + |
829 | + for(const auto & a: apps) |
830 | + { |
831 | + scopes::CategorisedResult res(cat); |
832 | + res.set_title(a.title); |
833 | + res.set_art(a.icon_url); |
834 | + res.set_uri(a.url); |
835 | + res[click::Query::ResultKeys::NAME] = a.name; |
836 | + res[click::Query::ResultKeys::DESCRIPTION] = a.description; |
837 | + res[click::Query::ResultKeys::MAIN_SCREENSHOT] = a.main_screenshot; |
838 | + res[click::Query::ResultKeys::INSTALLED] = true; |
839 | + res[click::Query::ResultKeys::VERSION] = a.version; |
840 | + replyProxy->push(res); |
841 | + } |
842 | +} |
843 | + |
844 | +struct click::Query::Private |
845 | +{ |
846 | + Private(const unity::scopes::CannedQuery& query, click::Index& index, const scopes::SearchMetadata& metadata) |
847 | + : query(query), |
848 | + index(index), |
849 | + meta(metadata) |
850 | + { |
851 | + } |
852 | + unity::scopes::CannedQuery query; |
853 | + click::Index& index; |
854 | + scopes::SearchMetadata meta; |
855 | +}; |
856 | + |
857 | +click::Query::Query(unity::scopes::CannedQuery const& query, click::Index& index, scopes::SearchMetadata const& metadata) |
858 | + : impl(new Private(query, index, metadata)) |
859 | +{ |
860 | +} |
861 | + |
862 | +void click::Query::cancelled() |
863 | +{ |
864 | + qDebug() << "cancelling search of" << QString::fromStdString(impl->query.query_string()); |
865 | +} |
866 | + |
867 | +click::Query::~Query() |
868 | +{ |
869 | + qDebug() << "destroying search"; |
870 | +} |
871 | + |
872 | +namespace |
873 | +{ |
874 | +click::Interface& clickInterfaceInstance() |
875 | +{ |
876 | + static QSharedPointer<click::KeyFileLocator> keyFileLocator(new click::KeyFileLocator()); |
877 | + static click::Interface iface(keyFileLocator); |
878 | + |
879 | + return iface; |
880 | +} |
881 | + |
882 | +} |
883 | + |
884 | +void click::Query::add_fake_store_app(scopes::SearchReplyProxy const& searchReply) |
885 | +{ |
886 | + static const std::string title = _("Get more apps in Ubuntu store"); |
887 | + auto name = title; |
888 | + |
889 | + std::string query = impl->query.query_string(); |
890 | + std::transform(query.begin(), query.end(), query.begin(), ::tolower); |
891 | + std::transform(name.begin(), name.end(), name.begin(), ::tolower); |
892 | + if (query.empty() || name.find(query) != std::string::npos) |
893 | + { |
894 | + scopes::CategoryRenderer rdr(CATEGORY_STORE); |
895 | + auto cat = searchReply->register_category("store", "", "", rdr); |
896 | + |
897 | + static const unity::scopes::CannedQuery store_scope("com.canonical.scopes.clickstore"); |
898 | + |
899 | + scopes::CategorisedResult res(cat); |
900 | + res.set_title(title); |
901 | + res.set_art(STORE_DATA_DIR "/apps-scope.svg"); |
902 | + res.set_uri(store_scope.to_uri()); |
903 | + res[click::Query::ResultKeys::NAME] = title; |
904 | + res[click::Query::ResultKeys::DESCRIPTION] = ""; |
905 | + res[click::Query::ResultKeys::MAIN_SCREENSHOT] = ""; |
906 | + res[click::Query::ResultKeys::INSTALLED] = true; |
907 | + res[click::Query::ResultKeys::VERSION] = ""; |
908 | + searchReply->push(res); |
909 | + } |
910 | +} |
911 | + |
912 | +void click::Query::run(scopes::SearchReplyProxy const& searchReply) |
913 | +{ |
914 | + auto query = impl->query.query_string(); |
915 | + std::string categoryTemplate = CATEGORY_APPS_SEARCH; |
916 | + if (query.empty()) { |
917 | + categoryTemplate = CATEGORY_APPS_DISPLAY; |
918 | + } |
919 | + auto localResults = clickInterfaceInstance().find_installed_apps( |
920 | + query); |
921 | + |
922 | + // Sort applications so that newest come first. |
923 | + std::sort(localResults.begin(), localResults.end(), [](const Application& a, const Application& b) { |
924 | + return a.installed_time > b.installed_time; |
925 | + }); |
926 | + |
927 | + push_local_results( |
928 | + searchReply, |
929 | + localResults, |
930 | + categoryTemplate); |
931 | + |
932 | + add_fake_store_app(searchReply); |
933 | +} |
934 | |
935 | === added file 'scope/clickapps/apps-query.h' |
936 | --- scope/clickapps/apps-query.h 1970-01-01 00:00:00 +0000 |
937 | +++ scope/clickapps/apps-query.h 2014-06-06 00:43:07 +0000 |
938 | @@ -0,0 +1,82 @@ |
939 | +/* |
940 | + * Copyright (C) 2014 Canonical Ltd. |
941 | + * |
942 | + * This program is free software: you can redistribute it and/or modify it |
943 | + * under the terms of the GNU General Public License version 3, as published |
944 | + * by the Free Software Foundation. |
945 | + * |
946 | + * This program is distributed in the hope that it will be useful, but |
947 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
948 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
949 | + * PURPOSE. See the GNU General Public License for more details. |
950 | + * |
951 | + * You should have received a copy of the GNU General Public License along |
952 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
953 | + * |
954 | + * In addition, as a special exception, the copyright holders give |
955 | + * permission to link the code of portions of this program with the |
956 | + * OpenSSL library under certain conditions as described in each |
957 | + * individual source file, and distribute linked combinations |
958 | + * including the two. |
959 | + * You must obey the GNU General Public License in all respects |
960 | + * for all of the code used other than OpenSSL. If you modify |
961 | + * file(s) with this exception, you may extend this exception to your |
962 | + * version of the file(s), but you are not obligated to do so. If you |
963 | + * do not wish to do so, delete this exception statement from your |
964 | + * version. If you delete this exception statement from all source |
965 | + * files in the program, then also delete it here. |
966 | + */ |
967 | + |
968 | +#ifndef APPS_QUERY_H |
969 | +#define APPS_QUERY_H |
970 | + |
971 | + |
972 | +#include <unity/scopes/SearchQueryBase.h> |
973 | + |
974 | +namespace scopes = unity::scopes; |
975 | + |
976 | +#include <QSharedPointer> |
977 | +#include <set> |
978 | + |
979 | + |
980 | +namespace click |
981 | +{ |
982 | + |
983 | +class Application; |
984 | +class Index; |
985 | + |
986 | +class Query : public scopes::SearchQueryBase |
987 | +{ |
988 | +public: |
989 | + struct ResultKeys |
990 | + { |
991 | + ResultKeys() = delete; |
992 | + |
993 | + constexpr static const char* NAME{"name"}; |
994 | + constexpr static const char* DESCRIPTION{"description"}; |
995 | + constexpr static const char* MAIN_SCREENSHOT{"main_screenshot"}; |
996 | + constexpr static const char* INSTALLED{"installed"}; |
997 | + constexpr static const char* DOWNLOAD_URL{"download_url"}; |
998 | + constexpr static const char* VERSION{"version"}; |
999 | + }; |
1000 | + |
1001 | + Query(unity::scopes::CannedQuery const& query, click::Index& index, scopes::SearchMetadata const& metadata); |
1002 | + virtual ~Query(); |
1003 | + |
1004 | + virtual void cancelled() override; |
1005 | + |
1006 | + virtual void run(scopes::SearchReplyProxy const& reply) override; |
1007 | + |
1008 | +protected: |
1009 | + virtual void add_fake_store_app(scopes::SearchReplyProxy const &replyProxy); |
1010 | + virtual void push_local_results(scopes::SearchReplyProxy const &replyProxy, |
1011 | + std::vector<click::Application> const &apps, |
1012 | + std::string& categoryTemplate); |
1013 | + |
1014 | +private: |
1015 | + struct Private; |
1016 | + QSharedPointer<Private> impl; |
1017 | +}; |
1018 | +} |
1019 | + |
1020 | +#endif // CLICK_QUERY_H |
1021 | |
1022 | === added file 'scope/clickapps/apps-scope.cpp' |
1023 | --- scope/clickapps/apps-scope.cpp 1970-01-01 00:00:00 +0000 |
1024 | +++ scope/clickapps/apps-scope.cpp 2014-06-06 00:43:07 +0000 |
1025 | @@ -0,0 +1,158 @@ |
1026 | +/* |
1027 | + * Copyright (C) 2014 Canonical Ltd. |
1028 | + * |
1029 | + * This program is free software: you can redistribute it and/or modify it |
1030 | + * under the terms of the GNU General Public License version 3, as published |
1031 | + * by the Free Software Foundation. |
1032 | + * |
1033 | + * This program is distributed in the hope that it will be useful, but |
1034 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
1035 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
1036 | + * PURPOSE. See the GNU General Public License for more details. |
1037 | + * |
1038 | + * You should have received a copy of the GNU General Public License along |
1039 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
1040 | + * |
1041 | + * In addition, as a special exception, the copyright holders give |
1042 | + * permission to link the code of portions of this program with the |
1043 | + * OpenSSL library under certain conditions as described in each |
1044 | + * individual source file, and distribute linked combinations |
1045 | + * including the two. |
1046 | + * You must obey the GNU General Public License in all respects |
1047 | + * for all of the code used other than OpenSSL. If you modify |
1048 | + * file(s) with this exception, you may extend this exception to your |
1049 | + * version of the file(s), but you are not obligated to do so. If you |
1050 | + * do not wish to do so, delete this exception statement from your |
1051 | + * version. If you delete this exception statement from all source |
1052 | + * files in the program, then also delete it here. |
1053 | + */ |
1054 | + |
1055 | +#include <click/qtbridge.h> |
1056 | +#include <click/preview.h> |
1057 | +#include <click/interface.h> |
1058 | +#include <click/scope_activation.h> |
1059 | + |
1060 | +#include <QSharedPointer> |
1061 | + |
1062 | +#include <click/key_file_locator.h> |
1063 | +#include <click/network_access_manager.h> |
1064 | +#include <click/click-i18n.h> |
1065 | +#include <unity/scopes/CannedQuery.h> |
1066 | + |
1067 | +#include "apps-scope.h" |
1068 | +#include "apps-query.h" |
1069 | + |
1070 | +namespace |
1071 | +{ |
1072 | +click::Interface& clickInterfaceInstance() |
1073 | +{ |
1074 | + static QSharedPointer<click::KeyFileLocator> keyFileLocator(new click::KeyFileLocator()); |
1075 | + static click::Interface iface(keyFileLocator); |
1076 | + return iface; |
1077 | +} |
1078 | +} |
1079 | + |
1080 | +click::Scope::Scope() |
1081 | +{ |
1082 | + nam.reset(new click::network::AccessManager()); |
1083 | + client.reset(new click::web::Client(nam)); |
1084 | + index.reset(new click::Index(client)); |
1085 | +} |
1086 | + |
1087 | +click::Scope::~Scope() |
1088 | +{ |
1089 | +} |
1090 | + |
1091 | +int click::Scope::start(std::string const&, scopes::RegistryProxy const&) |
1092 | +{ |
1093 | + setlocale(LC_ALL, ""); |
1094 | + bindtextdomain(GETTEXT_PACKAGE, GETTEXT_LOCALEDIR); |
1095 | + bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8"); |
1096 | + |
1097 | + return VERSION; |
1098 | +} |
1099 | + |
1100 | +void click::Scope::run() |
1101 | +{ |
1102 | + static const int zero = 0; |
1103 | + auto emptyCb = [this]() |
1104 | + { |
1105 | + }; |
1106 | + |
1107 | + qt::core::world::build_and_run(zero, nullptr, emptyCb); |
1108 | +} |
1109 | + |
1110 | +void click::Scope::stop() |
1111 | +{ |
1112 | + qt::core::world::destroy(); |
1113 | +} |
1114 | + |
1115 | +scopes::SearchQueryBase::UPtr click::Scope::search(unity::scopes::CannedQuery const& q, scopes::SearchMetadata const& metadata) |
1116 | +{ |
1117 | + return scopes::SearchQueryBase::UPtr(new click::Query(q, *index, metadata)); |
1118 | +} |
1119 | + |
1120 | + |
1121 | +unity::scopes::PreviewQueryBase::UPtr click::Scope::preview(const unity::scopes::Result& result, |
1122 | + const unity::scopes::ActionMetadata& metadata) { |
1123 | + qDebug() << "Scope::preview() called."; |
1124 | + return scopes::PreviewQueryBase::UPtr{new click::Preview(result, metadata, client, nam)}; |
1125 | +} |
1126 | + |
1127 | + |
1128 | +unity::scopes::ActivationQueryBase::UPtr click::Scope::perform_action(unity::scopes::Result const& result, unity::scopes::ActionMetadata const& metadata, std::string const& /* widget_id */, std::string const& action_id) |
1129 | +{ |
1130 | + if (action_id == click::Preview::Actions::CONFIRM_UNINSTALL) { |
1131 | + const unity::scopes::CannedQuery cquery("clickscope"); |
1132 | + return scopes::ActivationQueryBase::UPtr(new PerformUninstallAction(result, unity::scopes::ActivationResponse(cquery))); |
1133 | + } |
1134 | + |
1135 | + auto activation = new ScopeActivation(); |
1136 | + qDebug() << "perform_action called with action_id" << QString().fromStdString(action_id); |
1137 | + |
1138 | + if (action_id == click::Preview::Actions::UNINSTALL_CLICK) { |
1139 | + activation->setHint(click::Preview::Actions::UNINSTALL_CLICK, unity::scopes::Variant(true)); |
1140 | + activation->setStatus(unity::scopes::ActivationResponse::Status::ShowPreview); |
1141 | + } else if (action_id == click::Preview::Actions::CLOSE_PREVIEW) { |
1142 | + activation->setHint(click::Preview::Actions::CLOSE_PREVIEW, unity::scopes::Variant(true)); |
1143 | + activation->setStatus(unity::scopes::ActivationResponse::Status::ShowPreview); |
1144 | + } else if (action_id == click::Preview::Actions::RATED) { |
1145 | + scopes::VariantMap rating_info = metadata.scope_data().get_dict(); |
1146 | + // Cast to int because widget gives us double, which is wrong. |
1147 | + int rating = ((int)rating_info["rating"].get_double()); |
1148 | + std::string review_text = rating_info["review"].get_string(); |
1149 | + |
1150 | + // We have to get the values and then set them as hints here, to be |
1151 | + // able to pass them on to the Preview, which actually makes the |
1152 | + // call to submit. |
1153 | + activation->setHint("rating", scopes::Variant(rating)); |
1154 | + activation->setHint("review", scopes::Variant(review_text)); |
1155 | + activation->setHint(click::Preview::Actions::RATED, |
1156 | + scopes::Variant(true)); |
1157 | + activation->setStatus(scopes::ActivationResponse::Status::ShowPreview); |
1158 | + } |
1159 | + return scopes::ActivationQueryBase::UPtr(activation); |
1160 | +} |
1161 | + |
1162 | +#define EXPORT __attribute__ ((visibility ("default"))) |
1163 | + |
1164 | +extern "C" |
1165 | +{ |
1166 | + |
1167 | + EXPORT |
1168 | + unity::scopes::ScopeBase* |
1169 | + // cppcheck-suppress unusedFunction |
1170 | + UNITY_SCOPE_CREATE_FUNCTION() |
1171 | + { |
1172 | + return new click::Scope(); |
1173 | + } |
1174 | + |
1175 | + EXPORT |
1176 | + void |
1177 | + // cppcheck-suppress unusedFunction |
1178 | + UNITY_SCOPE_DESTROY_FUNCTION(unity::scopes::ScopeBase* scope_base) |
1179 | + { |
1180 | + delete scope_base; |
1181 | + } |
1182 | + |
1183 | +} |
1184 | |
1185 | === added file 'scope/clickapps/apps-scope.h' |
1186 | --- scope/clickapps/apps-scope.h 1970-01-01 00:00:00 +0000 |
1187 | +++ scope/clickapps/apps-scope.h 2014-06-06 00:43:07 +0000 |
1188 | @@ -0,0 +1,71 @@ |
1189 | +/* |
1190 | + * Copyright (C) 2014 Canonical Ltd. |
1191 | + * |
1192 | + * This program is free software: you can redistribute it and/or modify it |
1193 | + * under the terms of the GNU General Public License version 3, as published |
1194 | + * by the Free Software Foundation. |
1195 | + * |
1196 | + * This program is distributed in the hope that it will be useful, but |
1197 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
1198 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
1199 | + * PURPOSE. See the GNU General Public License for more details. |
1200 | + * |
1201 | + * You should have received a copy of the GNU General Public License along |
1202 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
1203 | + * |
1204 | + * In addition, as a special exception, the copyright holders give |
1205 | + * permission to link the code of portions of this program with the |
1206 | + * OpenSSL library under certain conditions as described in each |
1207 | + * individual source file, and distribute linked combinations |
1208 | + * including the two. |
1209 | + * You must obey the GNU General Public License in all respects |
1210 | + * for all of the code used other than OpenSSL. If you modify |
1211 | + * file(s) with this exception, you may extend this exception to your |
1212 | + * version of the file(s), but you are not obligated to do so. If you |
1213 | + * do not wish to do so, delete this exception statement from your |
1214 | + * version. If you delete this exception statement from all source |
1215 | + * files in the program, then also delete it here. |
1216 | + */ |
1217 | + |
1218 | +#ifndef APPS_SCOPE_H |
1219 | +#define APPS_SCOPE_H |
1220 | + |
1221 | +#include <click/network_access_manager.h> |
1222 | +#include <click/webclient.h> |
1223 | + |
1224 | +#include <unity/scopes/ScopeBase.h> |
1225 | +#include <unity/scopes/QueryBase.h> |
1226 | +#include <unity/scopes/ActivationQueryBase.h> |
1227 | + |
1228 | +#include <click/index.h> |
1229 | + |
1230 | +namespace scopes = unity::scopes; |
1231 | + |
1232 | +namespace click |
1233 | +{ |
1234 | +class Scope : public scopes::ScopeBase |
1235 | +{ |
1236 | +public: |
1237 | + Scope(); |
1238 | + ~Scope(); |
1239 | + |
1240 | + virtual int start(std::string const&, scopes::RegistryProxy const&) override; |
1241 | + |
1242 | + virtual void run() override; |
1243 | + virtual void stop() override; |
1244 | + |
1245 | + virtual scopes::SearchQueryBase::UPtr search(scopes::CannedQuery const& q, scopes::SearchMetadata const&) override; |
1246 | + unity::scopes::PreviewQueryBase::UPtr preview(const unity::scopes::Result&, |
1247 | + const unity::scopes::ActionMetadata&) override; |
1248 | + |
1249 | + virtual unity::scopes::ActivationQueryBase::UPtr perform_action(unity::scopes::Result const& result, unity::scopes::ActionMetadata const& metadata, std::string const& widget_id, std::string const& action_id) override; |
1250 | + |
1251 | +private: |
1252 | + QSharedPointer<click::network::AccessManager> nam; |
1253 | + QSharedPointer<click::web::Client> client; |
1254 | + QSharedPointer<click::Index> index; |
1255 | + |
1256 | + std::string installApplication(unity::scopes::Result const& result); |
1257 | +}; |
1258 | +} |
1259 | +#endif // CLICK_SCOPE_H |
1260 | |
1261 | === renamed directory 'scope/click' => 'scope/clickstore' |
1262 | === modified file 'scope/clickstore/CMakeLists.txt' |
1263 | --- scope/click/CMakeLists.txt 2014-05-26 14:02:45 +0000 |
1264 | +++ scope/clickstore/CMakeLists.txt 2014-06-06 00:43:07 +0000 |
1265 | @@ -8,19 +8,20 @@ |
1266 | -DGETTEXT_LOCALEDIR=\"${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LOCALEDIR}\" |
1267 | ) |
1268 | |
1269 | -add_library(${SCOPE_LIB_UNVERSIONED} SHARED |
1270 | - query.cpp |
1271 | - scope.cpp |
1272 | +add_library(${STORE_LIB_UNVERSIONED} SHARED |
1273 | + store-query.cpp |
1274 | + store-scope.cpp |
1275 | ) |
1276 | +set_target_properties(${STORE_LIB_UNVERSIONED} PROPERTIES PREFIX "") |
1277 | |
1278 | include_directories( |
1279 | ${CMAKE_SOURCE_DIR}/libclickscope |
1280 | ${JSON_CPP_INCLUDE_DIRS} |
1281 | ) |
1282 | |
1283 | -qt5_use_modules (${SCOPE_LIB_UNVERSIONED} Network) |
1284 | +qt5_use_modules (${STORE_LIB_UNVERSIONED} Network) |
1285 | |
1286 | -target_link_libraries (${SCOPE_LIB_UNVERSIONED} |
1287 | +target_link_libraries (${STORE_LIB_UNVERSIONED} |
1288 | ${SCOPE_LIB_NAME} |
1289 | ${JSON_CPP_LDFLAGS} |
1290 | ${UNITY_SCOPES_LDFLAGS} |
1291 | @@ -30,6 +31,6 @@ |
1292 | ) |
1293 | |
1294 | install( |
1295 | - TARGETS ${SCOPE_LIB_UNVERSIONED} |
1296 | - LIBRARY DESTINATION "${SCOPE_LIB_DIR}" |
1297 | + TARGETS ${STORE_LIB_UNVERSIONED} |
1298 | + LIBRARY DESTINATION "${STORE_LIB_DIR}" |
1299 | ) |
1300 | |
1301 | === renamed file 'scope/click/query.cpp' => 'scope/clickstore/store-query.cpp' |
1302 | --- scope/click/query.cpp 2014-05-26 14:02:45 +0000 |
1303 | +++ scope/clickstore/store-query.cpp 2014-06-06 00:43:07 +0000 |
1304 | @@ -28,9 +28,9 @@ |
1305 | */ |
1306 | |
1307 | #include <click/application.h> |
1308 | -#include "query.h" |
1309 | +#include <click/interface.h> |
1310 | +#include "store-query.h" |
1311 | #include <click/qtbridge.h> |
1312 | -#include <click/interface.h> |
1313 | |
1314 | #include <click/key_file_locator.h> |
1315 | |
1316 | @@ -48,6 +48,8 @@ |
1317 | |
1318 | #include <click/click-i18n.h> |
1319 | |
1320 | +using namespace click; |
1321 | + |
1322 | namespace |
1323 | { |
1324 | |
1325 | @@ -60,10 +62,10 @@ |
1326 | }, |
1327 | "components" : { |
1328 | "title" : "title", |
1329 | + "subtitle": "subtitle", |
1330 | "art" : { |
1331 | "field": "art", |
1332 | - "aspect-ratio": 1.6, |
1333 | - "fill-mode": "fit" |
1334 | + "aspect-ratio": 1.13 |
1335 | } |
1336 | } |
1337 | } |
1338 | @@ -89,32 +91,6 @@ |
1339 | |
1340 | } |
1341 | |
1342 | -void click::Query::push_local_results(scopes::SearchReplyProxy const &replyProxy, |
1343 | - std::vector<click::Application> const &apps, |
1344 | - std::string &categoryTemplate) |
1345 | -{ |
1346 | - scopes::CategoryRenderer rdr(categoryTemplate); |
1347 | - auto cat = replyProxy->register_category("local", _("My apps"), "", rdr); |
1348 | - |
1349 | - // cat might be null when the underlying query got cancelled. |
1350 | - if (!cat) |
1351 | - return; |
1352 | - |
1353 | - for(const auto & a: apps) |
1354 | - { |
1355 | - scopes::CategorisedResult res(cat); |
1356 | - res.set_title(a.title); |
1357 | - res.set_art(a.icon_url); |
1358 | - res.set_uri(a.url); |
1359 | - res[click::Query::ResultKeys::NAME] = a.name; |
1360 | - res[click::Query::ResultKeys::DESCRIPTION] = a.description; |
1361 | - res[click::Query::ResultKeys::MAIN_SCREENSHOT] = a.main_screenshot; |
1362 | - res[click::Query::ResultKeys::INSTALLED] = true; |
1363 | - res[click::Query::ResultKeys::VERSION] = a.version; |
1364 | - replyProxy->push(res); |
1365 | - } |
1366 | -} |
1367 | - |
1368 | struct click::Query::Private |
1369 | { |
1370 | Private(const unity::scopes::CannedQuery& query, click::Index& index, const scopes::SearchMetadata& metadata) |
1371 | @@ -145,9 +121,7 @@ |
1372 | impl->search_operation.cancel(); |
1373 | } |
1374 | |
1375 | -namespace |
1376 | -{ |
1377 | -click::Interface& clickInterfaceInstance() |
1378 | +click::Interface& click::Query::clickInterfaceInstance() |
1379 | { |
1380 | static QSharedPointer<click::KeyFileLocator> keyFileLocator(new click::KeyFileLocator()); |
1381 | static click::Interface iface(keyFileLocator); |
1382 | @@ -155,8 +129,6 @@ |
1383 | return iface; |
1384 | } |
1385 | |
1386 | -} |
1387 | - |
1388 | bool click::Query::push_result(scopes::SearchReplyProxy const& searchReply, const scopes::CategorisedResult &res) |
1389 | { |
1390 | return searchReply->push(res); |
1391 | @@ -184,7 +156,7 @@ |
1392 | } |
1393 | |
1394 | void click::Query::add_available_apps(scopes::SearchReplyProxy const& searchReply, |
1395 | - const std::set<std::string>& locallyInstalledApps, |
1396 | + const PackageNames& installedPackages, |
1397 | const std::string& categoryTemplate) |
1398 | { |
1399 | scopes::CategoryRenderer categoryRenderer(categoryTemplate); |
1400 | @@ -197,7 +169,7 @@ |
1401 | |
1402 | run_under_qt([=]() |
1403 | { |
1404 | - auto search_cb = [this, searchReply, category, locallyInstalledApps](PackageList packages) { |
1405 | + auto search_cb = [this, searchReply, category, installedPackages](PackageList packages) { |
1406 | qDebug("search callback"); |
1407 | |
1408 | // handle packages data |
1409 | @@ -205,15 +177,13 @@ |
1410 | qDebug() << "pushing result" << QString::fromStdString(p.name); |
1411 | try { |
1412 | scopes::CategorisedResult res(category); |
1413 | - if (locallyInstalledApps.count(p.name) > 0) { |
1414 | - qDebug() << "already installed" << QString::fromStdString(p.name); |
1415 | - continue; |
1416 | - } |
1417 | res.set_title(p.title); |
1418 | res.set_art(p.icon_url); |
1419 | res.set_uri(p.url); |
1420 | res[click::Query::ResultKeys::NAME] = p.name; |
1421 | - res[click::Query::ResultKeys::INSTALLED] = false; |
1422 | + bool installed = (installedPackages.count(p.name) > 0); |
1423 | + res[click::Query::ResultKeys::INSTALLED] = installed; |
1424 | + res["subtitle"] = installed ? "✔ Installed" : "FREE"; |
1425 | |
1426 | this->push_result(searchReply, res); |
1427 | } catch(const std::exception& e){ |
1428 | @@ -231,6 +201,23 @@ |
1429 | }); |
1430 | } |
1431 | |
1432 | +PackageNames click::Query::get_installed_packages() |
1433 | +{ |
1434 | + std::promise<PackageNames> installed_promise; |
1435 | + std::future<PackageNames> installed_future = installed_promise.get_future(); |
1436 | + |
1437 | + run_under_qt([&]() |
1438 | + { |
1439 | + clickInterfaceInstance().get_installed_packagenames( |
1440 | + [&installed_promise](PackageNames installedPackages, InterfaceError){ |
1441 | + installed_promise.set_value(installedPackages); |
1442 | + }); |
1443 | + }); |
1444 | + |
1445 | + return installed_future.get(); |
1446 | +} |
1447 | + |
1448 | + |
1449 | void click::Query::run(scopes::SearchReplyProxy const& searchReply) |
1450 | { |
1451 | auto query = impl->query.query_string(); |
1452 | @@ -238,18 +225,6 @@ |
1453 | if (query.empty()) { |
1454 | categoryTemplate = CATEGORY_APPS_DISPLAY; |
1455 | } |
1456 | - auto localResults = clickInterfaceInstance().find_installed_apps( |
1457 | - query); |
1458 | - |
1459 | - push_local_results( |
1460 | - searchReply, |
1461 | - localResults, |
1462 | - categoryTemplate); |
1463 | - |
1464 | - std::set<std::string> locallyInstalledApps; |
1465 | - for(const auto& app : localResults) { |
1466 | - locallyInstalledApps.insert(app.name); |
1467 | - } |
1468 | |
1469 | static const std::string no_net_hint("no-internet"); |
1470 | if (impl->meta.contains_hint(no_net_hint)) |
1471 | @@ -259,8 +234,7 @@ |
1472 | { |
1473 | return; |
1474 | } |
1475 | - |
1476 | } |
1477 | |
1478 | - add_available_apps(searchReply, locallyInstalledApps, categoryTemplate); |
1479 | + add_available_apps(searchReply, get_installed_packages(), categoryTemplate); |
1480 | } |
1481 | |
1482 | === renamed file 'scope/click/query.h' => 'scope/clickstore/store-query.h' |
1483 | --- scope/click/query.h 2014-05-14 18:34:20 +0000 |
1484 | +++ scope/clickstore/store-query.h 2014-06-06 00:43:07 +0000 |
1485 | @@ -27,8 +27,8 @@ |
1486 | * files in the program, then also delete it here. |
1487 | */ |
1488 | |
1489 | -#ifndef CLICK_QUERY_H |
1490 | -#define CLICK_QUERY_H |
1491 | +#ifndef STORE_QUERY_H |
1492 | +#define STORE_QUERY_H |
1493 | |
1494 | |
1495 | #include <unity/scopes/SearchQueryBase.h> |
1496 | @@ -36,8 +36,8 @@ |
1497 | namespace scopes = unity::scopes; |
1498 | |
1499 | #include <QSharedPointer> |
1500 | -#include <set> |
1501 | - |
1502 | +#include <unordered_set> |
1503 | +#include <click/interface.h> |
1504 | |
1505 | namespace click |
1506 | { |
1507 | @@ -78,12 +78,11 @@ |
1508 | virtual void run(scopes::SearchReplyProxy const& reply) override; |
1509 | |
1510 | protected: |
1511 | - virtual void add_available_apps(const scopes::SearchReplyProxy &searchReply, const std::set<std::string> &locallyInstalledApps, const std::string &category); |
1512 | + virtual void add_available_apps(const scopes::SearchReplyProxy &searchReply, const PackageNames &installedPackages, const std::string &category); |
1513 | + virtual click::Interface& clickInterfaceInstance(); |
1514 | + virtual PackageNames get_installed_packages(); |
1515 | virtual bool push_result(const scopes::SearchReplyProxy &searchReply, scopes::CategorisedResult const& res); |
1516 | virtual void finished(const scopes::SearchReplyProxy &searchReply); |
1517 | - virtual void push_local_results(scopes::SearchReplyProxy const &replyProxy, |
1518 | - std::vector<click::Application> const &apps, |
1519 | - std::string& categoryTemplate); |
1520 | virtual scopes::Category::SCPtr register_category(scopes::SearchReplyProxy const& searchReply, |
1521 | std::string const& id, |
1522 | std::string const& title, |
1523 | |
1524 | === renamed file 'scope/click/scope.cpp' => 'scope/clickstore/store-scope.cpp' |
1525 | --- scope/click/scope.cpp 2014-05-27 08:30:21 +0000 |
1526 | +++ scope/clickstore/store-scope.cpp 2014-06-06 00:43:07 +0000 |
1527 | @@ -28,8 +28,8 @@ |
1528 | */ |
1529 | |
1530 | #include <click/qtbridge.h> |
1531 | -#include "scope.h" |
1532 | -#include "query.h" |
1533 | +#include "store-scope.h" |
1534 | +#include "store-query.h" |
1535 | #include <click/preview.h> |
1536 | #include <click/interface.h> |
1537 | #include <click/scope_activation.h> |
1538 | |
1539 | === renamed file 'scope/click/scope.h' => 'scope/clickstore/store-scope.h' |
1540 | === modified file 'scope/tests/CMakeLists.txt' |
1541 | --- scope/tests/CMakeLists.txt 2014-05-26 14:27:31 +0000 |
1542 | +++ scope/tests/CMakeLists.txt 2014-06-06 00:43:07 +0000 |
1543 | @@ -22,7 +22,7 @@ |
1544 | qt5_use_modules(${CLICKSCOPE_TESTS_TARGET} Core DBus Network Test) |
1545 | |
1546 | target_link_libraries(${CLICKSCOPE_TESTS_TARGET} |
1547 | - ${SCOPE_LIB_UNVERSIONED} |
1548 | + ${STORE_LIB_UNVERSIONED} |
1549 | ${SCOPE_LIB_NAME} |
1550 | |
1551 | ${UNITY_SCOPES_LDFLAGS} |
1552 | |
1553 | === modified file 'scope/tests/click_interface_tool/CMakeLists.txt' |
1554 | --- scope/tests/click_interface_tool/CMakeLists.txt 2014-05-13 19:32:29 +0000 |
1555 | +++ scope/tests/click_interface_tool/CMakeLists.txt 2014-06-06 00:43:07 +0000 |
1556 | @@ -10,5 +10,5 @@ |
1557 | ) |
1558 | |
1559 | target_link_libraries (${CLICK_INTERFACE_TOOL_TARGET} |
1560 | - ${SCOPE_LIB_UNVERSIONED} |
1561 | + ${STORE_LIB_UNVERSIONED} |
1562 | ) |
1563 | |
1564 | === modified file 'scope/tests/click_interface_tool/click_interface_tool.cpp' |
1565 | --- scope/tests/click_interface_tool/click_interface_tool.cpp 2014-05-13 19:32:29 +0000 |
1566 | +++ scope/tests/click_interface_tool/click_interface_tool.cpp 2014-06-06 00:43:07 +0000 |
1567 | @@ -51,8 +51,8 @@ |
1568 | |
1569 | QObject::connect(&timer, &QTimer::timeout, [&]() { |
1570 | ci.get_dotdesktop_filename(std::string(argv[1]), |
1571 | - [&a] (std::string val, click::ManifestError error){ |
1572 | - if (error == click::ManifestError::NoError) { |
1573 | + [&a] (std::string val, click::InterfaceError error){ |
1574 | + if (error == click::InterfaceError::NoError) { |
1575 | std::cout << " Success, got dotdesktop:" << val << std::endl; |
1576 | } else { |
1577 | std::cout << " Error:" << val << std::endl; |
1578 | |
1579 | === modified file 'scope/tests/download_manager_tool/CMakeLists.txt' |
1580 | --- scope/tests/download_manager_tool/CMakeLists.txt 2014-02-27 17:24:07 +0000 |
1581 | +++ scope/tests/download_manager_tool/CMakeLists.txt 2014-06-06 00:43:07 +0000 |
1582 | @@ -10,5 +10,5 @@ |
1583 | ) |
1584 | |
1585 | target_link_libraries (${DOWNLOAD_MANAGER_TOOL_TARGET} |
1586 | - ${SCOPE_LIB_UNVERSIONED} |
1587 | + ${STORE_LIB_UNVERSIONED} |
1588 | ) |
1589 | |
1590 | === modified file 'scope/tests/integration/CMakeLists.txt' |
1591 | --- scope/tests/integration/CMakeLists.txt 2014-02-27 17:24:07 +0000 |
1592 | +++ scope/tests/integration/CMakeLists.txt 2014-06-06 00:43:07 +0000 |
1593 | @@ -17,7 +17,7 @@ |
1594 | qt5_use_modules(${INTEGRATION_TARGET} Core DBus Network Test) |
1595 | |
1596 | target_link_libraries (${INTEGRATION_TARGET} |
1597 | - ${SCOPE_LIB_UNVERSIONED} |
1598 | + ${STORE_LIB_UNVERSIONED} |
1599 | |
1600 | gmock |
1601 | gmock_main |
1602 | |
1603 | === modified file 'scope/tests/test_query.cpp' |
1604 | --- scope/tests/test_query.cpp 2014-05-21 13:42:45 +0000 |
1605 | +++ scope/tests/test_query.cpp 2014-06-06 00:43:07 +0000 |
1606 | @@ -34,7 +34,7 @@ |
1607 | #include <gmock/gmock.h> |
1608 | |
1609 | #include "click/qtbridge.h" |
1610 | -#include "click/query.h" |
1611 | +#include "clickstore/store-query.h" |
1612 | #include "click/index.h" |
1613 | #include "click/application.h" |
1614 | |
1615 | @@ -47,6 +47,7 @@ |
1616 | #include <unity/scopes/SearchReply.h> |
1617 | |
1618 | using namespace ::testing; |
1619 | +using namespace click; |
1620 | |
1621 | namespace |
1622 | { |
1623 | @@ -98,18 +99,20 @@ |
1624 | |
1625 | } |
1626 | void wrap_add_available_apps(const scopes::SearchReplyProxy &searchReply, |
1627 | - const std::set<std::string> &locallyInstalledApps, |
1628 | + const PackageNames &installedPackages, |
1629 | const std::string& categoryTemplate) |
1630 | { |
1631 | - add_available_apps(searchReply, locallyInstalledApps, categoryTemplate); |
1632 | + add_available_apps(searchReply, installedPackages, categoryTemplate); |
1633 | } |
1634 | MOCK_METHOD2(push_result, bool(scopes::SearchReplyProxy const&, scopes::CategorisedResult const&)); |
1635 | + MOCK_METHOD0(clickInterfaceInstance, click::Interface&()); |
1636 | MOCK_METHOD1(finished, void(scopes::SearchReplyProxy const&)); |
1637 | MOCK_METHOD5(register_category, scopes::Category::SCPtr(const scopes::SearchReplyProxy &searchReply, |
1638 | const std::string &id, |
1639 | const std::string &title, |
1640 | const std::string &icon, |
1641 | const scopes::CategoryRenderer &renderer_template)); |
1642 | + using click::Query::get_installed_packages; // allow tests to access protected method |
1643 | }; |
1644 | |
1645 | class MockQueryRun : public MockQueryBase { |
1646 | @@ -121,11 +124,12 @@ |
1647 | } |
1648 | MOCK_METHOD3(add_available_apps, |
1649 | void(scopes::SearchReplyProxy const&searchReply, |
1650 | - const std::set<std::string> &locallyInstalledApps, |
1651 | + const PackageNames &locallyInstalledApps, |
1652 | const std::string& categoryTemplate)); |
1653 | MOCK_METHOD3(push_local_results, void(scopes::SearchReplyProxy const &replyProxy, |
1654 | std::vector<click::Application> const &apps, |
1655 | std::string& categoryTemplate)); |
1656 | + MOCK_METHOD0(get_installed_packages, PackageNames()); |
1657 | }; |
1658 | |
1659 | class FakeCategory : public scopes::Category |
1660 | @@ -144,7 +148,7 @@ |
1661 | { |
1662 | MockIndex mock_index; |
1663 | scopes::SearchMetadata metadata("en_EN", "phone"); |
1664 | - std::set<std::string> no_installed_packages; |
1665 | + PackageNames no_installed_packages; |
1666 | const unity::scopes::CannedQuery query("foo.scope", FAKE_QUERY, ""); |
1667 | MockQuery q(query, mock_index, metadata); |
1668 | EXPECT_CALL(mock_index, do_search(FAKE_QUERY, _)).Times(1); |
1669 | @@ -163,7 +167,7 @@ |
1670 | }; |
1671 | MockIndex mock_index(packages); |
1672 | scopes::SearchMetadata metadata("en_EN", "phone"); |
1673 | - std::set<std::string> no_installed_packages; |
1674 | + PackageNames no_installed_packages; |
1675 | const unity::scopes::CannedQuery query("foo.scope", FAKE_QUERY, ""); |
1676 | MockQuery q(query, mock_index, metadata); |
1677 | EXPECT_CALL(mock_index, do_search(FAKE_QUERY, _)); |
1678 | @@ -185,7 +189,7 @@ |
1679 | }; |
1680 | MockIndex mock_index(packages); |
1681 | scopes::SearchMetadata metadata("en_EN", "phone"); |
1682 | - std::set<std::string> no_installed_packages; |
1683 | + PackageNames no_installed_packages; |
1684 | const unity::scopes::CannedQuery query("foo.scope", FAKE_QUERY, ""); |
1685 | MockQuery q(query, mock_index, metadata); |
1686 | EXPECT_CALL(mock_index, do_search(FAKE_QUERY, _)); |
1687 | @@ -206,7 +210,7 @@ |
1688 | }; |
1689 | MockIndex mock_index(packages); |
1690 | scopes::SearchMetadata metadata("en_EN", "phone"); |
1691 | - std::set<std::string> no_installed_packages; |
1692 | + PackageNames no_installed_packages; |
1693 | const unity::scopes::CannedQuery query("foo.scope", FAKE_QUERY, ""); |
1694 | MockQuery q(query, mock_index, metadata); |
1695 | EXPECT_CALL(mock_index, do_search(FAKE_QUERY, _)).Times(0); |
1696 | @@ -225,39 +229,94 @@ |
1697 | }; |
1698 | MockIndex mock_index(packages); |
1699 | scopes::SearchMetadata metadata("en_EN", "phone"); |
1700 | - std::set<std::string> no_installed_packages; |
1701 | + PackageNames no_installed_packages; |
1702 | const unity::scopes::CannedQuery query("foo.scope", FAKE_QUERY, ""); |
1703 | MockQueryRun q(query, mock_index, metadata); |
1704 | auto reply = scopes::SearchReplyProxy(); |
1705 | - EXPECT_CALL(q, push_local_results(_, _, _)); |
1706 | + EXPECT_CALL(q, get_installed_packages()).WillOnce(Return(no_installed_packages)); |
1707 | EXPECT_CALL(q, add_available_apps(reply, no_installed_packages, _)); |
1708 | |
1709 | q.run(reply); |
1710 | } |
1711 | |
1712 | MATCHER_P(HasPackageName, n, "") { return arg[click::Query::ResultKeys::NAME].get_string() == n; } |
1713 | - |
1714 | -TEST(QueryTest, testDuplicatesFilteredOnPackageName) |
1715 | -{ |
1716 | - click::PackageList packages { |
1717 | - {"org.example.app1", "app title1", 0.0, "icon", "uri"}, |
1718 | - {"org.example.app2", "app title2", 0.0, "icon", "uri"} |
1719 | - }; |
1720 | - MockIndex mock_index(packages); |
1721 | - scopes::SearchMetadata metadata("en_EN", "phone"); |
1722 | - std::set<std::string> one_installed_package { |
1723 | - "org.example.app2" |
1724 | - }; |
1725 | - const unity::scopes::CannedQuery query("foo.scope", FAKE_QUERY, ""); |
1726 | - MockQuery q(query, mock_index, metadata); |
1727 | - EXPECT_CALL(mock_index, do_search(FAKE_QUERY, _)); |
1728 | - |
1729 | - scopes::CategoryRenderer renderer("{}"); |
1730 | - auto ptrCat = std::make_shared<FakeCategory>("id", "", "", renderer); |
1731 | - EXPECT_CALL(q, register_category(_, _, _, _, _)).WillOnce(Return(ptrCat)); |
1732 | - |
1733 | - scopes::SearchReplyProxy reply; |
1734 | - auto expected_name = packages.front().name; |
1735 | - EXPECT_CALL(q, push_result(_, HasPackageName(expected_name))); |
1736 | - q.wrap_add_available_apps(reply, one_installed_package, FAKE_CATEGORY_TEMPLATE); |
1737 | +MATCHER_P(IsInstalled, b, "") { return arg[click::Query::ResultKeys::INSTALLED].get_bool() == b; } |
1738 | + |
1739 | +TEST(QueryTest, testDuplicatesNotFilteredAnymore) |
1740 | +{ |
1741 | + click::PackageList packages { |
1742 | + {"org.example.app1", "app title1", 0.0, "icon", "uri"}, |
1743 | + {"org.example.app2", "app title2", 0.0, "icon", "uri"} |
1744 | + }; |
1745 | + MockIndex mock_index(packages); |
1746 | + scopes::SearchMetadata metadata("en_EN", "phone"); |
1747 | + PackageNames one_installed_package { |
1748 | + "org.example.app2" |
1749 | + }; |
1750 | + const unity::scopes::CannedQuery query("foo.scope", FAKE_QUERY, ""); |
1751 | + MockQuery q(query, mock_index, metadata); |
1752 | + EXPECT_CALL(mock_index, do_search(FAKE_QUERY, _)); |
1753 | + |
1754 | + scopes::CategoryRenderer renderer("{}"); |
1755 | + auto ptrCat = std::make_shared<FakeCategory>("id", "", "", renderer); |
1756 | + EXPECT_CALL(q, register_category(_, _, _, _, _)).WillOnce(Return(ptrCat)); |
1757 | + |
1758 | + scopes::SearchReplyProxy reply; |
1759 | + auto expected_name1 = packages.front().name; |
1760 | + EXPECT_CALL(q, push_result(_, HasPackageName(expected_name1))); |
1761 | + auto expected_name2 = packages.back().name; |
1762 | + EXPECT_CALL(q, push_result(_, HasPackageName(expected_name2))); |
1763 | + q.wrap_add_available_apps(reply, one_installed_package, FAKE_CATEGORY_TEMPLATE); |
1764 | +} |
1765 | + |
1766 | +TEST(QueryTest, testInstalledPackagesFlaggedAsSuch) |
1767 | +{ |
1768 | + click::PackageList packages { |
1769 | + {"org.example.app1", "app title1", 0.0, "icon", "uri"}, |
1770 | + {"org.example.app2", "app title2", 0.0, "icon", "uri"} |
1771 | + }; |
1772 | + MockIndex mock_index(packages); |
1773 | + scopes::SearchMetadata metadata("en_EN", "phone"); |
1774 | + PackageNames one_installed_package { |
1775 | + "org.example.app2" |
1776 | + }; |
1777 | + const unity::scopes::CannedQuery query("foo.scope", FAKE_QUERY, ""); |
1778 | + MockQuery q(query, mock_index, metadata); |
1779 | + EXPECT_CALL(mock_index, do_search(FAKE_QUERY, _)); |
1780 | + |
1781 | + scopes::CategoryRenderer renderer("{}"); |
1782 | + auto ptrCat = std::make_shared<FakeCategory>("id", "", "", renderer); |
1783 | + EXPECT_CALL(q, register_category(_, _, _, _, _)).WillOnce(Return(ptrCat)); |
1784 | + |
1785 | + scopes::SearchReplyProxy reply; |
1786 | + EXPECT_CALL(q, push_result(_, IsInstalled(true))); |
1787 | + EXPECT_CALL(q, push_result(_, IsInstalled(false))); |
1788 | + q.wrap_add_available_apps(reply, one_installed_package, FAKE_CATEGORY_TEMPLATE); |
1789 | +} |
1790 | + |
1791 | +class FakeInterface : public click::Interface |
1792 | +{ |
1793 | +public: |
1794 | + MOCK_METHOD1(get_installed_packagenames, void(std::function<void(PackageNames, click::InterfaceError)> callback)); |
1795 | +}; |
1796 | + |
1797 | +TEST(QueryTest, testGetInstalledPackages) |
1798 | +{ |
1799 | + click::PackageList uninstalled_packages { |
1800 | + {"name", "title", 0.0, "icon", "uri"} |
1801 | + }; |
1802 | + MockIndex mock_index(uninstalled_packages); |
1803 | + scopes::SearchMetadata metadata("en_EN", "phone"); |
1804 | + const unity::scopes::CannedQuery query("foo.scope", FAKE_QUERY, ""); |
1805 | + MockQuery q(query, mock_index, metadata); |
1806 | + PackageNames installed_packages{"package_1"}; |
1807 | + |
1808 | + FakeInterface fake_interface; |
1809 | + EXPECT_CALL(q, clickInterfaceInstance()).WillOnce(ReturnRef(fake_interface)); |
1810 | + EXPECT_CALL(fake_interface, get_installed_packagenames(_)).WillOnce(Invoke( |
1811 | + [&](std::function<void(PackageNames, click::InterfaceError)> callback){ |
1812 | + callback(installed_packages, click::InterfaceError::NoError); |
1813 | + })); |
1814 | + |
1815 | + ASSERT_EQ(q.get_installed_packages(), installed_packages); |
1816 | } |
PASSED: Continuous integration, rev:281 jenkins. qa.ubuntu. com/job/ unity-team- unity-scope- click-devel- ci/92/ jenkins. qa.ubuntu. com/job/ unity-team- unity-scope- click-devel- utopic- amd64-ci/ 67 jenkins. qa.ubuntu. com/job/ unity-team- unity-scope- click-devel- utopic- armhf-ci/ 66 jenkins. qa.ubuntu. com/job/ unity-team- unity-scope- click-devel- utopic- armhf-ci/ 66/artifact/ work/output/ *zip*/output. zip jenkins. qa.ubuntu. com/job/ unity-team- unity-scope- click-devel- utopic- i386-ci/ 66
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/unity- team-unity- scope-click- devel-ci/ 92/rebuild
http://