Merge lp:~alecu/unity-scope-click/uninstall-scopes into lp:unity-scope-click/devel

Proposed by Alejandro J. Cura
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
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

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
282. By Alejandro J. Cura

Include subtitle with price or Installed

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
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

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'CMakeLists.txt'
--- CMakeLists.txt 2014-05-23 18:47:34 +0000
+++ CMakeLists.txt 2014-06-06 00:43:07 +0000
@@ -14,8 +14,10 @@
1414
15include(GNUInstallDirs)15include(GNUInstallDirs)
1616
17set(SCOPE_LIB_DIR ${CMAKE_INSTALL_FULL_LIBDIR}/unity-scopes/clickscope/)17set(STORE_LIB_DIR ${CMAKE_INSTALL_FULL_LIBDIR}/unity-scopes/clickstore/)
18set(SCOPE_DATA_DIR ${CMAKE_INSTALL_FULL_DATADIR}/unity/scopes/clickscope/)18set(STORE_DATA_DIR ${CMAKE_INSTALL_FULL_DATADIR}/unity/scopes/clickstore/)
19set(APPS_LIB_DIR ${CMAKE_INSTALL_FULL_LIBDIR}/unity-scopes/clickapps/)
20set(APPS_DATA_DIR ${CMAKE_INSTALL_FULL_DATADIR}/unity/scopes/clickapps/)
1921
20include(FindPkgConfig)22include(FindPkgConfig)
2123
@@ -32,8 +34,11 @@
32SET (SCOPE_LIB_VERSION 0.2.0)34SET (SCOPE_LIB_VERSION 0.2.0)
33SET (SCOPE_LIB_SOVERSION 0)35SET (SCOPE_LIB_SOVERSION 0)
34SET (SCOPE_LIB_API_VERSION 2.0)36SET (SCOPE_LIB_API_VERSION 2.0)
35SET (SCOPE_LIB_UNVERSIONED clickscope)37SET (STORE_LIB_UNVERSIONED com.canonical.scopes.clickstore)
36SET (SCOPE_LIB_NAME ${SCOPE_LIB_UNVERSIONED}-${SCOPE_LIB_API_VERSION})38SET (SCOPE_LIB_NAME clickscope)
39SET (STORE_LIB_NAME ${STORE_LIB_UNVERSIONED}-${SCOPE_LIB_API_VERSION})
40SET (APPS_LIB_UNVERSIONED scope)
41SET (APPS_LIB_NAME ${APPS_LIB_UNVERSIONED}-${SCOPE_LIB_API_VERSION})
3742
38# Build with system gmock and embedded gtest43# Build with system gmock and embedded gtest
39set (GMOCK_INCLUDE_DIR "/usr/include/gmock/include" CACHE PATH "gmock source include directory")44set (GMOCK_INCLUDE_DIR "/usr/include/gmock/include" CACHE PATH "gmock source include directory")
@@ -108,4 +113,4 @@
108113
109add_custom_target (check-leaks114add_custom_target (check-leaks
110 DEPENDS test-leaks115 DEPENDS test-leaks
111)
112\ No newline at end of file116\ No newline at end of file
117)
113118
=== modified file 'data/CMakeLists.txt'
--- data/CMakeLists.txt 2014-04-29 18:42:40 +0000
+++ data/CMakeLists.txt 2014-06-06 00:43:07 +0000
@@ -1,21 +1,43 @@
1find_program(INTLTOOL_MERGE intltool-merge)1find_program(INTLTOOL_MERGE intltool-merge)
2set(SCOPE_INI_TARGET clickscope.ini)2set(STORE_INI_TARGET com.canonical.scopes.clickstore.ini)
33set(APPS_INI_TARGET clickscope.ini)
4configure_file(4
5 ${SCOPE_INI_TARGET}.in.in5configure_file(
6 ${SCOPE_INI_TARGET}.in6 ${STORE_INI_TARGET}.in.in
7)7 ${STORE_INI_TARGET}.in
88)
9add_custom_target(${SCOPE_INI_TARGET} ALL9
10 COMMENT "Merging translations into ${SCOPE_INI_TARGET}"10configure_file(
11 COMMAND LC_ALL=C ${INTLTOOL_MERGE} -d -u ${CMAKE_SOURCE_DIR}/po ${SCOPE_INI_TARGET}.in ${SCOPE_INI_TARGET} >/dev/null11 ${APPS_INI_TARGET}.in.in
12)12 ${APPS_INI_TARGET}.in
1313)
14install(14
15 FILES clickscope-screenshot.jpg apps-scope.svg15add_custom_target(${STORE_INI_TARGET} ALL
16 DESTINATION "${SCOPE_DATA_DIR}"16 COMMENT "Merging translations into ${STORE_INI_TARGET}"
17)17 COMMAND LC_ALL=C ${INTLTOOL_MERGE} -d -u ${CMAKE_SOURCE_DIR}/po ${STORE_INI_TARGET}.in ${STORE_INI_TARGET} >/dev/null
18install(18)
19 FILES "${CMAKE_CURRENT_BINARY_DIR}/${SCOPE_INI_TARGET}"19
20 DESTINATION "${SCOPE_LIB_DIR}"20add_custom_target(${APPS_INI_TARGET} ALL
21 COMMENT "Merging translations into ${APPS_INI_TARGET}"
22 COMMAND LC_ALL=C ${INTLTOOL_MERGE} -d -u ${CMAKE_SOURCE_DIR}/po ${APPS_INI_TARGET}.in ${APPS_INI_TARGET} >/dev/null
23)
24
25install(
26 FILES clickscope-screenshot.jpg apps-scope.svg
27 DESTINATION "${STORE_DATA_DIR}"
28)
29
30install(
31 FILES clickscope-screenshot.jpg apps-scope.svg
32 DESTINATION "${APPS_DATA_DIR}"
33)
34
35install(
36 FILES "${CMAKE_CURRENT_BINARY_DIR}/${STORE_INI_TARGET}"
37 DESTINATION "${STORE_LIB_DIR}"
38)
39
40install(
41 FILES "${CMAKE_CURRENT_BINARY_DIR}/${APPS_INI_TARGET}"
42 DESTINATION "${APPS_LIB_DIR}"
21)43)
2244
=== added file 'data/clickscope.ini.in.in'
--- data/clickscope.ini.in.in 1970-01-01 00:00:00 +0000
+++ data/clickscope.ini.in.in 2014-06-06 00:43:07 +0000
@@ -0,0 +1,8 @@
1[ScopeConfig]
2_DisplayName=Apps
3_Description=Scope for searching the installed click apps
4Author=Canonical Ltd.
5Art=@APPS_DATA_DIR@/clickscope-screenshot.jpg
6Icon=@APPS_DATA_DIR@/apps-scope.svg
7SearchHint=clickscope.SearchHint
8HotKey=clickscope.HotKey
09
=== renamed file 'data/clickscope.ini.in.in' => 'data/com.canonical.scopes.clickstore.ini.in.in'
--- data/clickscope.ini.in.in 2014-04-29 18:42:40 +0000
+++ data/com.canonical.scopes.clickstore.ini.in.in 2014-06-06 00:43:07 +0000
@@ -1,8 +1,8 @@
1[ScopeConfig]1[ScopeConfig]
2_DisplayName=Apps2_DisplayName=Ubuntu Store
3_Description=Scope for searching the click app store3_Description=Scope for searching the click app store
4Author=Canonical Ltd.4Author=Canonical Ltd.
5Art=@SCOPE_DATA_DIR@/clickscope-screenshot.jpg5Art=@STORE_DATA_DIR@/clickscope-screenshot.jpg
6Icon=@SCOPE_DATA_DIR@/apps-scope.svg6Icon=@STORE_DATA_DIR@/apps-scope.svg
7SearchHint=clickscope.SearchHint7SearchHint=clickscope.SearchHint
8HotKey=clickscope.HotKey8HotKey=clickscope.HotKey
99
=== modified file 'libclickscope/click/interface.cpp'
--- libclickscope/click/interface.cpp 2014-05-26 14:02:45 +0000
+++ libclickscope/click/interface.cpp 2014-06-06 00:43:07 +0000
@@ -217,11 +217,6 @@
217 };217 };
218218
219 keyFileLocator->enumerateKeyFilesForInstalledApplications(enumerator);219 keyFileLocator->enumerateKeyFilesForInstalledApplications(enumerator);
220 // Sort applications so that newest come first.
221 std::sort(result.begin(), result.end(), [](const Application& a,
222 const Application& b) {
223 return a.installed_time > b.installed_time;
224 });
225 return result;220 return result;
226}221}
227222
@@ -321,7 +316,7 @@
321 return manifest;316 return manifest;
322}317}
323318
324void Interface::get_manifests(std::function<void(ManifestList, ManifestError)> callback)319void Interface::get_manifests(std::function<void(ManifestList, InterfaceError)> callback)
325{320{
326 std::string command = "click list --manifest";321 std::string command = "click list --manifest";
327 qDebug() << "Running command:" << command.c_str();322 qDebug() << "Running command:" << command.c_str();
@@ -329,18 +324,57 @@
329 if (code == 0) {324 if (code == 0) {
330 try {325 try {
331 ManifestList manifests = manifest_list_from_json(stdout_data);326 ManifestList manifests = manifest_list_from_json(stdout_data);
332 callback(manifests, ManifestError::NoError);327 callback(manifests, InterfaceError::NoError);
333 } catch (...) {328 } catch (...) {
334 callback(ManifestList(), ManifestError::ParseError);329 callback(ManifestList(), InterfaceError::ParseError);
335 }330 }
336 } else {331 } else {
337 callback(ManifestList(), ManifestError::CallError);332 callback(ManifestList(), InterfaceError::CallError);
333 }
334 });
335}
336
337PackageNames package_names_from_stdout(std::string stdout_data)
338{
339 PackageNames package_names;
340 const char newline = '\n';
341 const char tab = '\t';
342
343 size_t linestart = 0, tabpos;
344 size_t eof = stdout_data.length();
345
346 while (linestart < eof) {
347 tabpos = stdout_data.find_first_of(tab, linestart);
348 if (tabpos == std::string::npos) {
349 throw std::runtime_error("No tab in click list line");
350 }
351 package_names.insert(stdout_data.substr(linestart, tabpos-linestart));
352 linestart = stdout_data.find_first_of(newline, tabpos) + 1;
353 }
354
355 return package_names;
356}
357
358void Interface::get_installed_packagenames(std::function<void(PackageNames, InterfaceError)> callback)
359{
360 std::string command = "click list";
361 qDebug() << "Running command:" << command.c_str();
362 run_process(command, [callback](int code, const std::string& stdout_data, const std::string&) {
363 if (code == 0) {
364 try {
365 PackageNames package_names = package_names_from_stdout(stdout_data);
366 callback(package_names, InterfaceError::NoError);
367 } catch (...) {
368 callback({}, InterfaceError::ParseError);
369 }
370 } else {
371 callback({}, InterfaceError::CallError);
338 }372 }
339 });373 });
340}374}
341375
342void Interface::get_manifest_for_app(const std::string &app_id,376void Interface::get_manifest_for_app(const std::string &app_id,
343 std::function<void(Manifest, ManifestError)> callback)377 std::function<void(Manifest, InterfaceError)> callback)
344{378{
345 std::string command = "click info " + app_id;379 std::string command = "click info " + app_id;
346 qDebug() << "Running command:" << command.c_str();380 qDebug() << "Running command:" << command.c_str();
@@ -348,23 +382,23 @@
348 if (code == 0) {382 if (code == 0) {
349 try {383 try {
350 Manifest manifest = manifest_from_json(stdout_data);384 Manifest manifest = manifest_from_json(stdout_data);
351 callback(manifest, ManifestError::NoError);385 callback(manifest, InterfaceError::NoError);
352 } catch (...) {386 } catch (...) {
353 callback(Manifest(), ManifestError::ParseError);387 callback(Manifest(), InterfaceError::ParseError);
354 }388 }
355 } else {389 } else {
356 callback(Manifest(), ManifestError::CallError);390 callback(Manifest(), InterfaceError::CallError);
357 }391 }
358 });392 });
359}393}
360394
361void Interface::get_dotdesktop_filename(const std::string &app_id,395void Interface::get_dotdesktop_filename(const std::string &app_id,
362 std::function<void(std::string, ManifestError)> callback)396 std::function<void(std::string, InterfaceError)> callback)
363{397{
364 get_manifest_for_app(app_id, [app_id, callback] (Manifest manifest, ManifestError error) {398 get_manifest_for_app(app_id, [app_id, callback] (Manifest manifest, InterfaceError error) {
365 qDebug() << "in get_dotdesktop_filename callback";399 qDebug() << "in get_dotdesktop_filename callback";
366400
367 if (error != ManifestError::NoError){401 if (error != InterfaceError::NoError){
368 callback(std::string("Internal Error"), error);402 callback(std::string("Internal Error"), error);
369 return;403 return;
370 }404 }
@@ -372,10 +406,10 @@
372406
373 if (!manifest.name.empty()) {407 if (!manifest.name.empty()) {
374 std::string ddstr = manifest.name + "_" + manifest.first_app_name + "_" + manifest.version + ".desktop";408 std::string ddstr = manifest.name + "_" + manifest.first_app_name + "_" + manifest.version + ".desktop";
375 callback(ddstr, ManifestError::NoError);409 callback(ddstr, InterfaceError::NoError);
376 } else {410 } else {
377 qCritical() << "Warning: no manifest found for " << app_id.c_str();411 qCritical() << "Warning: no manifest found for " << app_id.c_str();
378 callback(std::string("Not found"), ManifestError::CallError);412 callback(std::string("Not found"), InterfaceError::CallError);
379 }413 }
380 });414 });
381}415}
382416
=== modified file 'libclickscope/click/interface.h'
--- libclickscope/click/interface.h 2014-05-26 14:02:45 +0000
+++ libclickscope/click/interface.h 2014-06-06 00:43:07 +0000
@@ -62,12 +62,14 @@
62 bool removable = false;62 bool removable = false;
63};63};
6464
65enum class ManifestError {NoError, CallError, ParseError};65enum class InterfaceError {NoError, CallError, ParseError};
66typedef std::list<Manifest> ManifestList;66typedef std::list<Manifest> ManifestList;
6767
68ManifestList manifest_list_from_json(const std::string& json);68ManifestList manifest_list_from_json(const std::string& json);
69Manifest manifest_from_json(const std::string& json);69Manifest manifest_from_json(const std::string& json);
7070
71typedef std::unordered_set<std::string> PackageNames;
72
71class Interface73class Interface
72{74{
73public:75public:
@@ -87,10 +89,11 @@
8789
88 static bool is_icon_identifier(const std::string &icon_id);90 static bool is_icon_identifier(const std::string &icon_id);
89 static std::string add_theme_scheme(const std::string &filename);91 static std::string add_theme_scheme(const std::string &filename);
90 virtual void get_manifests(std::function<void(ManifestList, ManifestError)> callback);92 virtual void get_manifests(std::function<void(ManifestList, InterfaceError)> callback);
91 virtual void get_manifest_for_app(const std::string &app_id, std::function<void(Manifest, ManifestError)> callback);93 virtual void get_installed_packagenames(std::function<void(PackageNames, InterfaceError)> callback);
94 virtual void get_manifest_for_app(const std::string &app_id, std::function<void(Manifest, InterfaceError)> callback);
92 virtual void get_dotdesktop_filename(const std::string &app_id,95 virtual void get_dotdesktop_filename(const std::string &app_id,
93 std::function<void(std::string filename, ManifestError)> callback);96 std::function<void(std::string filename, InterfaceError)> callback);
94 constexpr static const char* ENV_SHOW_DESKTOP_APPS {"CLICK_SCOPE_SHOW_DESKTOP_APPS"};97 constexpr static const char* ENV_SHOW_DESKTOP_APPS {"CLICK_SCOPE_SHOW_DESKTOP_APPS"};
95 virtual bool is_visible_app(const unity::util::IniParser& keyFile);98 virtual bool is_visible_app(const unity::util::IniParser& keyFile);
96 virtual bool show_desktop_apps();99 virtual bool show_desktop_apps();
97100
=== modified file 'libclickscope/click/preview.cpp'
--- libclickscope/click/preview.cpp 2014-05-26 14:02:45 +0000
+++ libclickscope/click/preview.cpp 2014-06-06 00:43:07 +0000
@@ -100,6 +100,10 @@
100 }100 }
101 } else {101 } else {
102 // metadata.scope_data() is Null, so we return an appropriate "default" preview:102 // metadata.scope_data() is Null, so we return an appropriate "default" preview:
103 if (result.uri().find("scope://") == 0)
104 {
105 return new InstalledScopePreview(result);
106 }
103 if (result["installed"].get_bool() == true) {107 if (result["installed"].get_bool() == true) {
104 return new InstalledPreview(result, metadata, client);108 return new InstalledPreview(result, metadata, client);
105 } else {109 } else {
@@ -435,7 +439,7 @@
435 if (!app_name.empty()) {439 if (!app_name.empty()) {
436 qt::core::world::enter_with_task([&]() {440 qt::core::world::enter_with_task([&]() {
437 click::Interface().get_manifest_for_app(app_name,441 click::Interface().get_manifest_for_app(app_name,
438 [&](Manifest manifest, ManifestError error) {442 [&](Manifest manifest, InterfaceError error) {
439 qDebug() << "Got manifest for:" << app_name.c_str();443 qDebug() << "Got manifest for:" << app_name.c_str();
440 removable = manifest.removable;444 removable = manifest.removable;
441445
@@ -443,7 +447,7 @@
443 review.package_name = manifest.name;447 review.package_name = manifest.name;
444 review.package_version = manifest.version;448 review.package_version = manifest.version;
445449
446 if (error != click::ManifestError::NoError) {450 if (error != click::InterfaceError::NoError) {
447 qDebug() << "There was an error getting the manifest for:" << app_name.c_str();451 qDebug() << "There was an error getting the manifest for:" << app_name.c_str();
448 }452 }
449 manifest_promise.set_value(true);453 manifest_promise.set_value(true);
@@ -532,9 +536,9 @@
532 auto ft = qt::core::world::enter_with_task([this, name, callback] ()536 auto ft = qt::core::world::enter_with_task([this, name, callback] ()
533 {537 {
534 click::Interface().get_dotdesktop_filename(name,538 click::Interface().get_dotdesktop_filename(name,
535 [callback] (std::string val, click::ManifestError error) {539 [callback] (std::string val, click::InterfaceError error) {
536 std::string uri;540 std::string uri;
537 if (error == click::ManifestError::NoError) {541 if (error == click::InterfaceError::NoError) {
538 uri = "application:///" + val;542 uri = "application:///" + val;
539 }543 }
540 callback(uri);544 callback(uri);
@@ -547,6 +551,30 @@
547 }551 }
548}552}
549553
554// class InstalledScopePreview
555// this is a temporary fallback preview to get into the Store scope, the proper
556// requires 'store' category to be treated special (like 'local') in unity8 shell.
557
558InstalledScopePreview::InstalledScopePreview(const unity::scopes::Result& result)
559 : PreviewStrategy(result)
560{
561}
562
563void InstalledScopePreview::run(unity::scopes::PreviewReplyProxy const& reply)
564{
565 scopes::PreviewWidget actions("actions", "actions");
566 {
567 scopes::VariantBuilder builder;
568 builder.add_tuple({
569 {"id", scopes::Variant("search")},
570 {"uri", scopes::Variant(result.uri())},
571 {"label", scopes::Variant(_("Search"))}
572 });
573 actions.add_attribute_value("actions", builder.end());
574 }
575
576 reply->push({actions});
577}
550578
551// class PurchasingPreview579// class PurchasingPreview
552580
553581
=== modified file 'libclickscope/click/preview.h'
--- libclickscope/click/preview.h 2014-05-26 14:02:45 +0000
+++ libclickscope/click/preview.h 2014-06-06 00:43:07 +0000
@@ -172,6 +172,13 @@
172 scopes::ActionMetadata metadata;172 scopes::ActionMetadata metadata;
173};173};
174174
175class InstalledScopePreview : public PreviewStrategy
176{
177public:
178 InstalledScopePreview(const unity::scopes::Result& result);
179 void run(unity::scopes::PreviewReplyProxy const& reply) override;
180};
181
175class PurchasingPreview : public PreviewStrategy182class PurchasingPreview : public PreviewStrategy
176{183{
177public:184public:
178185
=== modified file 'libclickscope/click/scope_activation.cpp'
--- libclickscope/click/scope_activation.cpp 2014-05-26 14:02:45 +0000
+++ libclickscope/click/scope_activation.cpp 2014-06-06 00:43:07 +0000
@@ -28,6 +28,9 @@
28 */28 */
2929
30#include "scope_activation.h"30#include "scope_activation.h"
31#include <click/package.h>
32#include <click/interface.h>
33#include <click/qtbridge.h>
31#include <unity/scopes/ActivationResponse.h>34#include <unity/scopes/ActivationResponse.h>
3235
33unity::scopes::ActivationResponse click::ScopeActivation::activate()36unity::scopes::ActivationResponse click::ScopeActivation::activate()
@@ -46,3 +49,31 @@
46{49{
47 hints_[key] = value;50 hints_[key] = value;
48}51}
52
53click::PerformUninstallAction::PerformUninstallAction(const unity::scopes::Result& result, const unity::scopes::ActivationResponse& response)
54 : result(result),
55 response(response)
56{
57}
58
59unity::scopes::ActivationResponse click::PerformUninstallAction::activate()
60{
61 click::Package package;
62 package.title = result.title();
63 package.name = result["name"].get_string();
64 package.version = result["version"].get_string();
65 qt::core::world::enter_with_task([this, package] ()
66 {
67 click::PackageManager manager;
68 manager.uninstall(package, [&](int code, std::string stderr_content) {
69 if (code != 0) {
70 qDebug() << "Error removing package:" << stderr_content.c_str();
71 } else {
72 qDebug() << "successfully removed package";
73
74 }
75 } );
76 });
77
78 return response;
79}
4980
=== modified file 'libclickscope/click/scope_activation.h'
--- libclickscope/click/scope_activation.h 2014-05-26 14:02:45 +0000
+++ libclickscope/click/scope_activation.h 2014-06-06 00:43:07 +0000
@@ -31,10 +31,23 @@
31#define CLICK_SCOPE_ACTIVATION_H31#define CLICK_SCOPE_ACTIVATION_H
3232
33#include <unity/scopes/ActivationQueryBase.h>33#include <unity/scopes/ActivationQueryBase.h>
34#include <unity/scopes/ActivationResponse.h>
35#include <unity/scopes/Result.h>
3436
35namespace click37namespace click
36{38{
3739
40class PerformUninstallAction: public unity::scopes::ActivationQueryBase
41{
42public:
43 PerformUninstallAction(const unity::scopes::Result& result, const unity::scopes::ActivationResponse& response);
44 unity::scopes::ActivationResponse activate() override;
45
46private:
47 unity::scopes::Result result;
48 unity::scopes::ActivationResponse response;
49};
50
38class ScopeActivation : public unity::scopes::ActivationQueryBase51class ScopeActivation : public unity::scopes::ActivationQueryBase
39{52{
40 unity::scopes::ActivationResponse activate() override;53 unity::scopes::ActivationResponse activate() override;
4154
=== modified file 'libclickscope/tests/test_interface.cpp'
--- libclickscope/tests/test_interface.cpp 2014-05-26 14:27:31 +0000
+++ libclickscope/tests/test_interface.cpp 2014-06-06 00:43:07 +0000
@@ -118,8 +118,9 @@
118118
119class ClickInterfaceTest : public ::testing::Test {119class ClickInterfaceTest : public ::testing::Test {
120public:120public:
121 MOCK_METHOD2(manifest_callback, void(Manifest, ManifestError));121 MOCK_METHOD2(manifest_callback, void(Manifest, InterfaceError));
122 MOCK_METHOD2(manifests_callback, void(ManifestList, ManifestError));122 MOCK_METHOD2(manifests_callback, void(ManifestList, InterfaceError));
123 MOCK_METHOD2(installed_callback, void(PackageNames, InterfaceError));
123};124};
124125
125}126}
@@ -326,7 +327,7 @@
326 std::string command = "click info " + FAKE_PACKAGENAME;327 std::string command = "click info " + FAKE_PACKAGENAME;
327 EXPECT_CALL(iface, run_process(command, _)).328 EXPECT_CALL(iface, run_process(command, _)).
328 Times(1);329 Times(1);
329 iface.get_manifest_for_app(FAKE_PACKAGENAME, [](Manifest, ManifestError){});330 iface.get_manifest_for_app(FAKE_PACKAGENAME, [](Manifest, InterfaceError){});
330}331}
331332
332TEST_F(ClickInterfaceTest, testGetManifestForAppParseError)333TEST_F(ClickInterfaceTest, testGetManifestForAppParseError)
@@ -339,9 +340,9 @@
339 const std::string&)> callback){340 const std::string&)> callback){
340 callback(0, "INVALID JSON", "");341 callback(0, "INVALID JSON", "");
341 }));342 }));
342 EXPECT_CALL(*this, manifest_callback(_, ManifestError::ParseError));343 EXPECT_CALL(*this, manifest_callback(_, InterfaceError::ParseError));
343 iface.get_manifest_for_app(FAKE_PACKAGENAME, [this](Manifest manifest,344 iface.get_manifest_for_app(FAKE_PACKAGENAME, [this](Manifest manifest,
344 ManifestError error){345 InterfaceError error){
345 manifest_callback(manifest, error);346 manifest_callback(manifest, error);
346 });347 });
347}348}
@@ -356,9 +357,9 @@
356 const std::string&)> callback){357 const std::string&)> callback){
357 callback(-1, "", "CRITICAL: FAIL");358 callback(-1, "", "CRITICAL: FAIL");
358 }));359 }));
359 EXPECT_CALL(*this, manifest_callback(_, ManifestError::CallError));360 EXPECT_CALL(*this, manifest_callback(_, InterfaceError::CallError));
360 iface.get_manifest_for_app(FAKE_PACKAGENAME, [this](Manifest manifest,361 iface.get_manifest_for_app(FAKE_PACKAGENAME, [this](Manifest manifest,
361 ManifestError error){362 InterfaceError error){
362 manifest_callback(manifest, error);363 manifest_callback(manifest, error);
363 });364 });
364}365}
@@ -374,8 +375,8 @@
374 callback(0, FAKE_JSON_MANIFEST_REMOVABLE, "");375 callback(0, FAKE_JSON_MANIFEST_REMOVABLE, "");
375 }));376 }));
376 iface.get_manifest_for_app(FAKE_PACKAGENAME, [](Manifest manifest,377 iface.get_manifest_for_app(FAKE_PACKAGENAME, [](Manifest manifest,
377 ManifestError error){378 InterfaceError error){
378 ASSERT_TRUE(error == ManifestError::NoError);379 ASSERT_TRUE(error == InterfaceError::NoError);
379 ASSERT_TRUE(manifest.removable);380 ASSERT_TRUE(manifest.removable);
380 });381 });
381}382}
@@ -391,8 +392,8 @@
391 callback(0, FAKE_JSON_MANIFEST_NONREMOVABLE, "");392 callback(0, FAKE_JSON_MANIFEST_NONREMOVABLE, "");
392 }));393 }));
393 iface.get_manifest_for_app(FAKE_PACKAGENAME, [](Manifest manifest,394 iface.get_manifest_for_app(FAKE_PACKAGENAME, [](Manifest manifest,
394 ManifestError error){395 InterfaceError error){
395 ASSERT_TRUE(error == ManifestError::NoError);396 ASSERT_TRUE(error == InterfaceError::NoError);
396 ASSERT_FALSE(manifest.removable);397 ASSERT_FALSE(manifest.removable);
397 });398 });
398}399}
@@ -403,7 +404,7 @@
403 std::string command = "click list --manifest";404 std::string command = "click list --manifest";
404 EXPECT_CALL(iface, run_process(command, _)).405 EXPECT_CALL(iface, run_process(command, _)).
405 Times(1);406 Times(1);
406 iface.get_manifests([](ManifestList, ManifestError){});407 iface.get_manifests([](ManifestList, InterfaceError){});
407}408}
408409
409TEST_F(ClickInterfaceTest, testGetManifestsParseError)410TEST_F(ClickInterfaceTest, testGetManifestsParseError)
@@ -416,8 +417,8 @@
416 const std::string&)> callback){417 const std::string&)> callback){
417 callback(0, "INVALID JSON", "");418 callback(0, "INVALID JSON", "");
418 }));419 }));
419 EXPECT_CALL(*this, manifests_callback(_, ManifestError::ParseError));420 EXPECT_CALL(*this, manifests_callback(_, InterfaceError::ParseError));
420 iface.get_manifests([this](ManifestList manifests, ManifestError error){421 iface.get_manifests([this](ManifestList manifests, InterfaceError error){
421 manifests_callback(manifests, error);422 manifests_callback(manifests, error);
422 });423 });
423}424}
@@ -432,8 +433,8 @@
432 const std::string&)> callback){433 const std::string&)> callback){
433 callback(-1, "", "CRITICAL: FAIL");434 callback(-1, "", "CRITICAL: FAIL");
434 }));435 }));
435 EXPECT_CALL(*this, manifests_callback(_, ManifestError::CallError));436 EXPECT_CALL(*this, manifests_callback(_, InterfaceError::CallError));
436 iface.get_manifests([this](ManifestList manifests, ManifestError error){437 iface.get_manifests([this](ManifestList manifests, InterfaceError error){
437 manifests_callback(manifests, error);438 manifests_callback(manifests, error);
438 });439 });
439}440}
@@ -452,8 +453,69 @@
452 const std::string&)> callback){453 const std::string&)> callback){
453 callback(0, expected_str, "");454 callback(0, expected_str, "");
454 }));455 }));
455 iface.get_manifests([expected](ManifestList manifests, ManifestError error){456 iface.get_manifests([expected](ManifestList manifests, InterfaceError error){
456 ASSERT_TRUE(error == ManifestError::NoError);457 ASSERT_TRUE(error == InterfaceError::NoError);
457 ASSERT_TRUE(manifests.size() == expected.size());458 ASSERT_TRUE(manifests.size() == expected.size());
458 });459 });
459}460}
461
462TEST(ClickInterface, testGetInstalledPackagesCorrectCommand)
463{
464 FakeClickInterface iface;
465 std::string command = "click list";
466 EXPECT_CALL(iface, run_process(command, _)).
467 Times(1);
468 iface.get_installed_packagenames([](PackageNames, InterfaceError){});
469}
470
471TEST_F(ClickInterfaceTest, testGetInstalledPackagesParseError)
472{
473 FakeClickInterface iface;
474 EXPECT_CALL(iface, run_process(_, _)).
475 Times(1).
476 WillOnce(Invoke([&](const std::string&,
477 std::function<void(int, const std::string&,
478 const std::string&)> callback){
479 callback(0, "valid\t\nINVALID LINE\n", "");
480 }));
481 EXPECT_CALL(*this, installed_callback(_, InterfaceError::ParseError));
482 iface.get_installed_packagenames([this](PackageNames package_names, InterfaceError error){
483 installed_callback(package_names, error);
484 });
485}
486
487TEST_F(ClickInterfaceTest, testGetInstalledPackagesCommandFailed)
488{
489 FakeClickInterface iface;
490 EXPECT_CALL(iface, run_process(_, _)).
491 Times(1).
492 WillOnce(Invoke([&](const std::string&,
493 std::function<void(int, const std::string&,
494 const std::string&)> callback){
495 callback(-1, "", "CRITICAL: FAIL");
496 }));
497 EXPECT_CALL(*this, installed_callback(_, InterfaceError::CallError));
498 iface.get_installed_packagenames([this](PackageNames package_names, InterfaceError error){
499 installed_callback(package_names, error);
500 });
501}
502
503TEST_F(ClickInterfaceTest, testGetInstalledPackagesParsed)
504{
505 FakeClickInterface iface;
506 std::string sample_stdout = "ABC\t0.1\nDEF\t0.2\n";
507 PackageNames expected{"ABC", "DEF"};
508
509 EXPECT_CALL(iface, run_process(_, _)).
510 Times(1).
511 WillOnce(Invoke([&](const std::string&,
512 std::function<void(int, const std::string&,
513 const std::string&)> callback){
514 callback(0, sample_stdout, "");
515 }));
516 iface.get_installed_packagenames([expected](PackageNames package_names, InterfaceError error){
517 ASSERT_EQ(error, InterfaceError::NoError);
518 ASSERT_EQ(package_names, expected);
519 });
520}
521
460522
=== modified file 'po/POTFILES.in'
--- po/POTFILES.in 2014-04-29 18:42:40 +0000
+++ po/POTFILES.in 2014-06-06 00:43:07 +0000
@@ -1,3 +1,5 @@
1[type: gettext/ini] data/clickscope.ini.in.in1[type: gettext/ini] data/com.canonical.scopes.clickstore.ini.in.in
2scope/click/preview.cpp2data/clickscope.ini.in.in
3scope/click/query.cpp3libclickscope/click/preview.cpp
4scope/clickapps/apps-query.cpp
5scope/clickstore/store-query.cpp
46
=== modified file 'scope/CMakeLists.txt'
--- scope/CMakeLists.txt 2014-01-28 08:49:16 +0000
+++ scope/CMakeLists.txt 2014-06-06 00:43:07 +0000
@@ -1,2 +1,3 @@
1add_subdirectory(click)
2add_subdirectory(tests)
3\ No newline at end of file1\ No newline at end of file
2add_subdirectory(clickstore)
3add_subdirectory(clickapps)
4add_subdirectory(tests)
45
=== added directory 'scope/clickapps'
=== added file 'scope/clickapps/CMakeLists.txt'
--- scope/clickapps/CMakeLists.txt 1970-01-01 00:00:00 +0000
+++ scope/clickapps/CMakeLists.txt 2014-06-06 00:43:07 +0000
@@ -0,0 +1,37 @@
1SET (CMAKE_INCLUDE_CURRENT_DIR ON)
2SET (CMAKE_AUTOMOC ON)
3find_package (Qt5Core REQUIRED)
4pkg_check_modules(JSON_CPP REQUIRED jsoncpp)
5
6add_definitions(
7 -DGETTEXT_PACKAGE=\"${PROJECT_NAME}\"
8 -DGETTEXT_LOCALEDIR=\"${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LOCALEDIR}\"
9 -DSTORE_DATA_DIR="${STORE_DATA_DIR}"
10)
11
12add_library(${APPS_LIB_UNVERSIONED} SHARED
13 apps-query.cpp
14 apps-scope.cpp
15)
16set_target_properties(${APPS_LIB_UNVERSIONED} PROPERTIES PREFIX "")
17
18include_directories(
19 ${CMAKE_SOURCE_DIR}/libclickscope
20 ${JSON_CPP_INCLUDE_DIRS}
21)
22
23qt5_use_modules (${APPS_LIB_UNVERSIONED} Network)
24
25target_link_libraries (${APPS_LIB_UNVERSIONED}
26 ${SCOPE_LIB_NAME}
27 ${JSON_CPP_LDFLAGS}
28 ${UNITY_SCOPES_LDFLAGS}
29 ${UBUNTUONE_LDFLAGS}
30 ${UBUNTU_DOWNLOAD_MANAGER_CLIENT_LDFLAGS}
31 ${UBUNTU_DOWNLOAD_MANAGER_COMMON_LDFLAGS}
32)
33
34install(
35 TARGETS ${APPS_LIB_UNVERSIONED}
36 LIBRARY DESTINATION "${APPS_LIB_DIR}"
37 )
038
=== added file 'scope/clickapps/apps-query.cpp'
--- scope/clickapps/apps-query.cpp 1970-01-01 00:00:00 +0000
+++ scope/clickapps/apps-query.cpp 2014-06-06 00:43:07 +0000
@@ -0,0 +1,218 @@
1/*
2 * Copyright (C) 2014 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3, as published
6 * by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranties of
10 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * In addition, as a special exception, the copyright holders give
17 * permission to link the code of portions of this program with the
18 * OpenSSL library under certain conditions as described in each
19 * individual source file, and distribute linked combinations
20 * including the two.
21 * You must obey the GNU General Public License in all respects
22 * for all of the code used other than OpenSSL. If you modify
23 * file(s) with this exception, you may extend this exception to your
24 * version of the file(s), but you are not obligated to do so. If you
25 * do not wish to do so, delete this exception statement from your
26 * version. If you delete this exception statement from all source
27 * files in the program, then also delete it here.
28 */
29
30#include <click/application.h>
31#include <click/interface.h>
32
33#include <click/key_file_locator.h>
34
35#include <unity/scopes/CategoryRenderer.h>
36#include <unity/scopes/CategorisedResult.h>
37#include <unity/scopes/CannedQuery.h>
38#include <unity/scopes/SearchReply.h>
39#include <unity/scopes/SearchMetadata.h>
40
41#include <vector>
42
43#include <click/click-i18n.h>
44#include "apps-query.h"
45
46namespace
47{
48
49std::string CATEGORY_APPS_DISPLAY = R"(
50 {
51 "schema-version" : 1,
52 "template" : {
53 "category-layout" : "grid",
54 "card-size": "small"
55 },
56 "components" : {
57 "title" : "title",
58 "art" : {
59 "field": "art",
60 "aspect-ratio": 1.6,
61 "fill-mode": "fit"
62 }
63 }
64 }
65)";
66
67std::string CATEGORY_APPS_SEARCH = R"(
68 {
69 "schema-version" : 1,
70 "template" : {
71 "category-layout" : "grid",
72 "card-layout" : "horizontal",
73 "card-size": "large"
74 },
75 "components" : {
76 "title" : "title",
77 "mascot" : {
78 "field": "art"
79 },
80 "subtitle": "publisher"
81 }
82 }
83)";
84
85static const char CATEGORY_STORE[] = R"(
86{
87 "schema-version": 1,
88 "template": {
89 "category-layout": "grid",
90 "card-size": "medium",
91 "card-background": "color:///#E9E9E9"
92 },
93 "components": {
94 "title": "title",
95 "subtitle": "author",
96 "mascot": {
97 "field": "art"
98 },
99 "background": "background"
100 }
101}
102)";
103
104
105}
106
107void click::Query::push_local_results(scopes::SearchReplyProxy const &replyProxy,
108 std::vector<click::Application> const &apps,
109 std::string &categoryTemplate)
110{
111 scopes::CategoryRenderer rdr(categoryTemplate);
112 auto cat = replyProxy->register_category("local", "", "", rdr);
113
114 for(const auto & a: apps)
115 {
116 scopes::CategorisedResult res(cat);
117 res.set_title(a.title);
118 res.set_art(a.icon_url);
119 res.set_uri(a.url);
120 res[click::Query::ResultKeys::NAME] = a.name;
121 res[click::Query::ResultKeys::DESCRIPTION] = a.description;
122 res[click::Query::ResultKeys::MAIN_SCREENSHOT] = a.main_screenshot;
123 res[click::Query::ResultKeys::INSTALLED] = true;
124 res[click::Query::ResultKeys::VERSION] = a.version;
125 replyProxy->push(res);
126 }
127}
128
129struct click::Query::Private
130{
131 Private(const unity::scopes::CannedQuery& query, click::Index& index, const scopes::SearchMetadata& metadata)
132 : query(query),
133 index(index),
134 meta(metadata)
135 {
136 }
137 unity::scopes::CannedQuery query;
138 click::Index& index;
139 scopes::SearchMetadata meta;
140};
141
142click::Query::Query(unity::scopes::CannedQuery const& query, click::Index& index, scopes::SearchMetadata const& metadata)
143 : impl(new Private(query, index, metadata))
144{
145}
146
147void click::Query::cancelled()
148{
149 qDebug() << "cancelling search of" << QString::fromStdString(impl->query.query_string());
150}
151
152click::Query::~Query()
153{
154 qDebug() << "destroying search";
155}
156
157namespace
158{
159click::Interface& clickInterfaceInstance()
160{
161 static QSharedPointer<click::KeyFileLocator> keyFileLocator(new click::KeyFileLocator());
162 static click::Interface iface(keyFileLocator);
163
164 return iface;
165}
166
167}
168
169void click::Query::add_fake_store_app(scopes::SearchReplyProxy const& searchReply)
170{
171 static const std::string title = _("Get more apps in Ubuntu store");
172 auto name = title;
173
174 std::string query = impl->query.query_string();
175 std::transform(query.begin(), query.end(), query.begin(), ::tolower);
176 std::transform(name.begin(), name.end(), name.begin(), ::tolower);
177 if (query.empty() || name.find(query) != std::string::npos)
178 {
179 scopes::CategoryRenderer rdr(CATEGORY_STORE);
180 auto cat = searchReply->register_category("store", "", "", rdr);
181
182 static const unity::scopes::CannedQuery store_scope("com.canonical.scopes.clickstore");
183
184 scopes::CategorisedResult res(cat);
185 res.set_title(title);
186 res.set_art(STORE_DATA_DIR "/apps-scope.svg");
187 res.set_uri(store_scope.to_uri());
188 res[click::Query::ResultKeys::NAME] = title;
189 res[click::Query::ResultKeys::DESCRIPTION] = "";
190 res[click::Query::ResultKeys::MAIN_SCREENSHOT] = "";
191 res[click::Query::ResultKeys::INSTALLED] = true;
192 res[click::Query::ResultKeys::VERSION] = "";
193 searchReply->push(res);
194 }
195}
196
197void click::Query::run(scopes::SearchReplyProxy const& searchReply)
198{
199 auto query = impl->query.query_string();
200 std::string categoryTemplate = CATEGORY_APPS_SEARCH;
201 if (query.empty()) {
202 categoryTemplate = CATEGORY_APPS_DISPLAY;
203 }
204 auto localResults = clickInterfaceInstance().find_installed_apps(
205 query);
206
207 // Sort applications so that newest come first.
208 std::sort(localResults.begin(), localResults.end(), [](const Application& a, const Application& b) {
209 return a.installed_time > b.installed_time;
210 });
211
212 push_local_results(
213 searchReply,
214 localResults,
215 categoryTemplate);
216
217 add_fake_store_app(searchReply);
218}
0219
=== added file 'scope/clickapps/apps-query.h'
--- scope/clickapps/apps-query.h 1970-01-01 00:00:00 +0000
+++ scope/clickapps/apps-query.h 2014-06-06 00:43:07 +0000
@@ -0,0 +1,82 @@
1/*
2 * Copyright (C) 2014 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3, as published
6 * by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranties of
10 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * In addition, as a special exception, the copyright holders give
17 * permission to link the code of portions of this program with the
18 * OpenSSL library under certain conditions as described in each
19 * individual source file, and distribute linked combinations
20 * including the two.
21 * You must obey the GNU General Public License in all respects
22 * for all of the code used other than OpenSSL. If you modify
23 * file(s) with this exception, you may extend this exception to your
24 * version of the file(s), but you are not obligated to do so. If you
25 * do not wish to do so, delete this exception statement from your
26 * version. If you delete this exception statement from all source
27 * files in the program, then also delete it here.
28 */
29
30#ifndef APPS_QUERY_H
31#define APPS_QUERY_H
32
33
34#include <unity/scopes/SearchQueryBase.h>
35
36namespace scopes = unity::scopes;
37
38#include <QSharedPointer>
39#include <set>
40
41
42namespace click
43{
44
45class Application;
46class Index;
47
48class Query : public scopes::SearchQueryBase
49{
50public:
51 struct ResultKeys
52 {
53 ResultKeys() = delete;
54
55 constexpr static const char* NAME{"name"};
56 constexpr static const char* DESCRIPTION{"description"};
57 constexpr static const char* MAIN_SCREENSHOT{"main_screenshot"};
58 constexpr static const char* INSTALLED{"installed"};
59 constexpr static const char* DOWNLOAD_URL{"download_url"};
60 constexpr static const char* VERSION{"version"};
61 };
62
63 Query(unity::scopes::CannedQuery const& query, click::Index& index, scopes::SearchMetadata const& metadata);
64 virtual ~Query();
65
66 virtual void cancelled() override;
67
68 virtual void run(scopes::SearchReplyProxy const& reply) override;
69
70protected:
71 virtual void add_fake_store_app(scopes::SearchReplyProxy const &replyProxy);
72 virtual void push_local_results(scopes::SearchReplyProxy const &replyProxy,
73 std::vector<click::Application> const &apps,
74 std::string& categoryTemplate);
75
76private:
77 struct Private;
78 QSharedPointer<Private> impl;
79};
80}
81
82#endif // CLICK_QUERY_H
083
=== added file 'scope/clickapps/apps-scope.cpp'
--- scope/clickapps/apps-scope.cpp 1970-01-01 00:00:00 +0000
+++ scope/clickapps/apps-scope.cpp 2014-06-06 00:43:07 +0000
@@ -0,0 +1,158 @@
1/*
2 * Copyright (C) 2014 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3, as published
6 * by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranties of
10 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * In addition, as a special exception, the copyright holders give
17 * permission to link the code of portions of this program with the
18 * OpenSSL library under certain conditions as described in each
19 * individual source file, and distribute linked combinations
20 * including the two.
21 * You must obey the GNU General Public License in all respects
22 * for all of the code used other than OpenSSL. If you modify
23 * file(s) with this exception, you may extend this exception to your
24 * version of the file(s), but you are not obligated to do so. If you
25 * do not wish to do so, delete this exception statement from your
26 * version. If you delete this exception statement from all source
27 * files in the program, then also delete it here.
28 */
29
30#include <click/qtbridge.h>
31#include <click/preview.h>
32#include <click/interface.h>
33#include <click/scope_activation.h>
34
35#include <QSharedPointer>
36
37#include <click/key_file_locator.h>
38#include <click/network_access_manager.h>
39#include <click/click-i18n.h>
40#include <unity/scopes/CannedQuery.h>
41
42#include "apps-scope.h"
43#include "apps-query.h"
44
45namespace
46{
47click::Interface& clickInterfaceInstance()
48{
49 static QSharedPointer<click::KeyFileLocator> keyFileLocator(new click::KeyFileLocator());
50 static click::Interface iface(keyFileLocator);
51 return iface;
52}
53}
54
55click::Scope::Scope()
56{
57 nam.reset(new click::network::AccessManager());
58 client.reset(new click::web::Client(nam));
59 index.reset(new click::Index(client));
60}
61
62click::Scope::~Scope()
63{
64}
65
66int click::Scope::start(std::string const&, scopes::RegistryProxy const&)
67{
68 setlocale(LC_ALL, "");
69 bindtextdomain(GETTEXT_PACKAGE, GETTEXT_LOCALEDIR);
70 bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
71
72 return VERSION;
73}
74
75void click::Scope::run()
76{
77 static const int zero = 0;
78 auto emptyCb = [this]()
79 {
80 };
81
82 qt::core::world::build_and_run(zero, nullptr, emptyCb);
83}
84
85void click::Scope::stop()
86{
87 qt::core::world::destroy();
88}
89
90scopes::SearchQueryBase::UPtr click::Scope::search(unity::scopes::CannedQuery const& q, scopes::SearchMetadata const& metadata)
91{
92 return scopes::SearchQueryBase::UPtr(new click::Query(q, *index, metadata));
93}
94
95
96unity::scopes::PreviewQueryBase::UPtr click::Scope::preview(const unity::scopes::Result& result,
97 const unity::scopes::ActionMetadata& metadata) {
98 qDebug() << "Scope::preview() called.";
99 return scopes::PreviewQueryBase::UPtr{new click::Preview(result, metadata, client, nam)};
100}
101
102
103unity::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)
104{
105 if (action_id == click::Preview::Actions::CONFIRM_UNINSTALL) {
106 const unity::scopes::CannedQuery cquery("clickscope");
107 return scopes::ActivationQueryBase::UPtr(new PerformUninstallAction(result, unity::scopes::ActivationResponse(cquery)));
108 }
109
110 auto activation = new ScopeActivation();
111 qDebug() << "perform_action called with action_id" << QString().fromStdString(action_id);
112
113 if (action_id == click::Preview::Actions::UNINSTALL_CLICK) {
114 activation->setHint(click::Preview::Actions::UNINSTALL_CLICK, unity::scopes::Variant(true));
115 activation->setStatus(unity::scopes::ActivationResponse::Status::ShowPreview);
116 } else if (action_id == click::Preview::Actions::CLOSE_PREVIEW) {
117 activation->setHint(click::Preview::Actions::CLOSE_PREVIEW, unity::scopes::Variant(true));
118 activation->setStatus(unity::scopes::ActivationResponse::Status::ShowPreview);
119 } else if (action_id == click::Preview::Actions::RATED) {
120 scopes::VariantMap rating_info = metadata.scope_data().get_dict();
121 // Cast to int because widget gives us double, which is wrong.
122 int rating = ((int)rating_info["rating"].get_double());
123 std::string review_text = rating_info["review"].get_string();
124
125 // We have to get the values and then set them as hints here, to be
126 // able to pass them on to the Preview, which actually makes the
127 // call to submit.
128 activation->setHint("rating", scopes::Variant(rating));
129 activation->setHint("review", scopes::Variant(review_text));
130 activation->setHint(click::Preview::Actions::RATED,
131 scopes::Variant(true));
132 activation->setStatus(scopes::ActivationResponse::Status::ShowPreview);
133 }
134 return scopes::ActivationQueryBase::UPtr(activation);
135}
136
137#define EXPORT __attribute__ ((visibility ("default")))
138
139extern "C"
140{
141
142 EXPORT
143 unity::scopes::ScopeBase*
144 // cppcheck-suppress unusedFunction
145 UNITY_SCOPE_CREATE_FUNCTION()
146 {
147 return new click::Scope();
148 }
149
150 EXPORT
151 void
152 // cppcheck-suppress unusedFunction
153 UNITY_SCOPE_DESTROY_FUNCTION(unity::scopes::ScopeBase* scope_base)
154 {
155 delete scope_base;
156 }
157
158}
0159
=== added file 'scope/clickapps/apps-scope.h'
--- scope/clickapps/apps-scope.h 1970-01-01 00:00:00 +0000
+++ scope/clickapps/apps-scope.h 2014-06-06 00:43:07 +0000
@@ -0,0 +1,71 @@
1/*
2 * Copyright (C) 2014 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3, as published
6 * by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranties of
10 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * In addition, as a special exception, the copyright holders give
17 * permission to link the code of portions of this program with the
18 * OpenSSL library under certain conditions as described in each
19 * individual source file, and distribute linked combinations
20 * including the two.
21 * You must obey the GNU General Public License in all respects
22 * for all of the code used other than OpenSSL. If you modify
23 * file(s) with this exception, you may extend this exception to your
24 * version of the file(s), but you are not obligated to do so. If you
25 * do not wish to do so, delete this exception statement from your
26 * version. If you delete this exception statement from all source
27 * files in the program, then also delete it here.
28 */
29
30#ifndef APPS_SCOPE_H
31#define APPS_SCOPE_H
32
33#include <click/network_access_manager.h>
34#include <click/webclient.h>
35
36#include <unity/scopes/ScopeBase.h>
37#include <unity/scopes/QueryBase.h>
38#include <unity/scopes/ActivationQueryBase.h>
39
40#include <click/index.h>
41
42namespace scopes = unity::scopes;
43
44namespace click
45{
46class Scope : public scopes::ScopeBase
47{
48public:
49 Scope();
50 ~Scope();
51
52 virtual int start(std::string const&, scopes::RegistryProxy const&) override;
53
54 virtual void run() override;
55 virtual void stop() override;
56
57 virtual scopes::SearchQueryBase::UPtr search(scopes::CannedQuery const& q, scopes::SearchMetadata const&) override;
58 unity::scopes::PreviewQueryBase::UPtr preview(const unity::scopes::Result&,
59 const unity::scopes::ActionMetadata&) override;
60
61 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;
62
63private:
64 QSharedPointer<click::network::AccessManager> nam;
65 QSharedPointer<click::web::Client> client;
66 QSharedPointer<click::Index> index;
67
68 std::string installApplication(unity::scopes::Result const& result);
69};
70}
71#endif // CLICK_SCOPE_H
072
=== renamed directory 'scope/click' => 'scope/clickstore'
=== modified file 'scope/clickstore/CMakeLists.txt'
--- scope/click/CMakeLists.txt 2014-05-26 14:02:45 +0000
+++ scope/clickstore/CMakeLists.txt 2014-06-06 00:43:07 +0000
@@ -8,19 +8,20 @@
8 -DGETTEXT_LOCALEDIR=\"${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LOCALEDIR}\"8 -DGETTEXT_LOCALEDIR=\"${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LOCALEDIR}\"
9)9)
1010
11add_library(${SCOPE_LIB_UNVERSIONED} SHARED11add_library(${STORE_LIB_UNVERSIONED} SHARED
12 query.cpp12 store-query.cpp
13 scope.cpp13 store-scope.cpp
14)14)
15set_target_properties(${STORE_LIB_UNVERSIONED} PROPERTIES PREFIX "")
1516
16include_directories(17include_directories(
17 ${CMAKE_SOURCE_DIR}/libclickscope18 ${CMAKE_SOURCE_DIR}/libclickscope
18 ${JSON_CPP_INCLUDE_DIRS}19 ${JSON_CPP_INCLUDE_DIRS}
19)20)
2021
21qt5_use_modules (${SCOPE_LIB_UNVERSIONED} Network)22qt5_use_modules (${STORE_LIB_UNVERSIONED} Network)
2223
23target_link_libraries (${SCOPE_LIB_UNVERSIONED}24target_link_libraries (${STORE_LIB_UNVERSIONED}
24 ${SCOPE_LIB_NAME}25 ${SCOPE_LIB_NAME}
25 ${JSON_CPP_LDFLAGS}26 ${JSON_CPP_LDFLAGS}
26 ${UNITY_SCOPES_LDFLAGS}27 ${UNITY_SCOPES_LDFLAGS}
@@ -30,6 +31,6 @@
30)31)
3132
32install(33install(
33 TARGETS ${SCOPE_LIB_UNVERSIONED}34 TARGETS ${STORE_LIB_UNVERSIONED}
34 LIBRARY DESTINATION "${SCOPE_LIB_DIR}"35 LIBRARY DESTINATION "${STORE_LIB_DIR}"
35 )36 )
3637
=== renamed file 'scope/click/query.cpp' => 'scope/clickstore/store-query.cpp'
--- scope/click/query.cpp 2014-05-26 14:02:45 +0000
+++ scope/clickstore/store-query.cpp 2014-06-06 00:43:07 +0000
@@ -28,9 +28,9 @@
28 */28 */
2929
30#include <click/application.h>30#include <click/application.h>
31#include "query.h"31#include <click/interface.h>
32#include "store-query.h"
32#include <click/qtbridge.h>33#include <click/qtbridge.h>
33#include <click/interface.h>
3434
35#include <click/key_file_locator.h>35#include <click/key_file_locator.h>
3636
@@ -48,6 +48,8 @@
4848
49#include <click/click-i18n.h>49#include <click/click-i18n.h>
5050
51using namespace click;
52
51namespace53namespace
52{54{
5355
@@ -60,10 +62,10 @@
60 },62 },
61 "components" : {63 "components" : {
62 "title" : "title",64 "title" : "title",
65 "subtitle": "subtitle",
63 "art" : {66 "art" : {
64 "field": "art",67 "field": "art",
65 "aspect-ratio": 1.6,68 "aspect-ratio": 1.13
66 "fill-mode": "fit"
67 }69 }
68 }70 }
69 }71 }
@@ -89,32 +91,6 @@
8991
90}92}
9193
92void click::Query::push_local_results(scopes::SearchReplyProxy const &replyProxy,
93 std::vector<click::Application> const &apps,
94 std::string &categoryTemplate)
95{
96 scopes::CategoryRenderer rdr(categoryTemplate);
97 auto cat = replyProxy->register_category("local", _("My apps"), "", rdr);
98
99 // cat might be null when the underlying query got cancelled.
100 if (!cat)
101 return;
102
103 for(const auto & a: apps)
104 {
105 scopes::CategorisedResult res(cat);
106 res.set_title(a.title);
107 res.set_art(a.icon_url);
108 res.set_uri(a.url);
109 res[click::Query::ResultKeys::NAME] = a.name;
110 res[click::Query::ResultKeys::DESCRIPTION] = a.description;
111 res[click::Query::ResultKeys::MAIN_SCREENSHOT] = a.main_screenshot;
112 res[click::Query::ResultKeys::INSTALLED] = true;
113 res[click::Query::ResultKeys::VERSION] = a.version;
114 replyProxy->push(res);
115 }
116}
117
118struct click::Query::Private94struct click::Query::Private
119{95{
120 Private(const unity::scopes::CannedQuery& query, click::Index& index, const scopes::SearchMetadata& metadata)96 Private(const unity::scopes::CannedQuery& query, click::Index& index, const scopes::SearchMetadata& metadata)
@@ -145,9 +121,7 @@
145 impl->search_operation.cancel();121 impl->search_operation.cancel();
146}122}
147123
148namespace124click::Interface& click::Query::clickInterfaceInstance()
149{
150click::Interface& clickInterfaceInstance()
151{125{
152 static QSharedPointer<click::KeyFileLocator> keyFileLocator(new click::KeyFileLocator());126 static QSharedPointer<click::KeyFileLocator> keyFileLocator(new click::KeyFileLocator());
153 static click::Interface iface(keyFileLocator);127 static click::Interface iface(keyFileLocator);
@@ -155,8 +129,6 @@
155 return iface;129 return iface;
156}130}
157131
158}
159
160bool click::Query::push_result(scopes::SearchReplyProxy const& searchReply, const scopes::CategorisedResult &res)132bool click::Query::push_result(scopes::SearchReplyProxy const& searchReply, const scopes::CategorisedResult &res)
161{133{
162 return searchReply->push(res);134 return searchReply->push(res);
@@ -184,7 +156,7 @@
184}156}
185157
186void click::Query::add_available_apps(scopes::SearchReplyProxy const& searchReply,158void click::Query::add_available_apps(scopes::SearchReplyProxy const& searchReply,
187 const std::set<std::string>& locallyInstalledApps,159 const PackageNames& installedPackages,
188 const std::string& categoryTemplate)160 const std::string& categoryTemplate)
189{161{
190 scopes::CategoryRenderer categoryRenderer(categoryTemplate);162 scopes::CategoryRenderer categoryRenderer(categoryTemplate);
@@ -197,7 +169,7 @@
197169
198 run_under_qt([=]()170 run_under_qt([=]()
199 {171 {
200 auto search_cb = [this, searchReply, category, locallyInstalledApps](PackageList packages) {172 auto search_cb = [this, searchReply, category, installedPackages](PackageList packages) {
201 qDebug("search callback");173 qDebug("search callback");
202174
203 // handle packages data175 // handle packages data
@@ -205,15 +177,13 @@
205 qDebug() << "pushing result" << QString::fromStdString(p.name);177 qDebug() << "pushing result" << QString::fromStdString(p.name);
206 try {178 try {
207 scopes::CategorisedResult res(category);179 scopes::CategorisedResult res(category);
208 if (locallyInstalledApps.count(p.name) > 0) {
209 qDebug() << "already installed" << QString::fromStdString(p.name);
210 continue;
211 }
212 res.set_title(p.title);180 res.set_title(p.title);
213 res.set_art(p.icon_url);181 res.set_art(p.icon_url);
214 res.set_uri(p.url);182 res.set_uri(p.url);
215 res[click::Query::ResultKeys::NAME] = p.name;183 res[click::Query::ResultKeys::NAME] = p.name;
216 res[click::Query::ResultKeys::INSTALLED] = false;184 bool installed = (installedPackages.count(p.name) > 0);
185 res[click::Query::ResultKeys::INSTALLED] = installed;
186 res["subtitle"] = installed ? "✔ Installed" : "FREE";
217187
218 this->push_result(searchReply, res);188 this->push_result(searchReply, res);
219 } catch(const std::exception& e){189 } catch(const std::exception& e){
@@ -231,6 +201,23 @@
231 });201 });
232}202}
233203
204PackageNames click::Query::get_installed_packages()
205{
206 std::promise<PackageNames> installed_promise;
207 std::future<PackageNames> installed_future = installed_promise.get_future();
208
209 run_under_qt([&]()
210 {
211 clickInterfaceInstance().get_installed_packagenames(
212 [&installed_promise](PackageNames installedPackages, InterfaceError){
213 installed_promise.set_value(installedPackages);
214 });
215 });
216
217 return installed_future.get();
218}
219
220
234void click::Query::run(scopes::SearchReplyProxy const& searchReply)221void click::Query::run(scopes::SearchReplyProxy const& searchReply)
235{222{
236 auto query = impl->query.query_string();223 auto query = impl->query.query_string();
@@ -238,18 +225,6 @@
238 if (query.empty()) {225 if (query.empty()) {
239 categoryTemplate = CATEGORY_APPS_DISPLAY;226 categoryTemplate = CATEGORY_APPS_DISPLAY;
240 }227 }
241 auto localResults = clickInterfaceInstance().find_installed_apps(
242 query);
243
244 push_local_results(
245 searchReply,
246 localResults,
247 categoryTemplate);
248
249 std::set<std::string> locallyInstalledApps;
250 for(const auto& app : localResults) {
251 locallyInstalledApps.insert(app.name);
252 }
253228
254 static const std::string no_net_hint("no-internet");229 static const std::string no_net_hint("no-internet");
255 if (impl->meta.contains_hint(no_net_hint))230 if (impl->meta.contains_hint(no_net_hint))
@@ -259,8 +234,7 @@
259 {234 {
260 return;235 return;
261 }236 }
262
263 }237 }
264238
265 add_available_apps(searchReply, locallyInstalledApps, categoryTemplate);239 add_available_apps(searchReply, get_installed_packages(), categoryTemplate);
266}240}
267241
=== renamed file 'scope/click/query.h' => 'scope/clickstore/store-query.h'
--- scope/click/query.h 2014-05-14 18:34:20 +0000
+++ scope/clickstore/store-query.h 2014-06-06 00:43:07 +0000
@@ -27,8 +27,8 @@
27 * files in the program, then also delete it here.27 * files in the program, then also delete it here.
28 */28 */
2929
30#ifndef CLICK_QUERY_H30#ifndef STORE_QUERY_H
31#define CLICK_QUERY_H31#define STORE_QUERY_H
3232
3333
34#include <unity/scopes/SearchQueryBase.h>34#include <unity/scopes/SearchQueryBase.h>
@@ -36,8 +36,8 @@
36namespace scopes = unity::scopes;36namespace scopes = unity::scopes;
3737
38#include <QSharedPointer>38#include <QSharedPointer>
39#include <set>39#include <unordered_set>
4040#include <click/interface.h>
4141
42namespace click42namespace click
43{43{
@@ -78,12 +78,11 @@
78 virtual void run(scopes::SearchReplyProxy const& reply) override;78 virtual void run(scopes::SearchReplyProxy const& reply) override;
7979
80protected:80protected:
81 virtual void add_available_apps(const scopes::SearchReplyProxy &searchReply, const std::set<std::string> &locallyInstalledApps, const std::string &category);81 virtual void add_available_apps(const scopes::SearchReplyProxy &searchReply, const PackageNames &installedPackages, const std::string &category);
82 virtual click::Interface& clickInterfaceInstance();
83 virtual PackageNames get_installed_packages();
82 virtual bool push_result(const scopes::SearchReplyProxy &searchReply, scopes::CategorisedResult const& res);84 virtual bool push_result(const scopes::SearchReplyProxy &searchReply, scopes::CategorisedResult const& res);
83 virtual void finished(const scopes::SearchReplyProxy &searchReply);85 virtual void finished(const scopes::SearchReplyProxy &searchReply);
84 virtual void push_local_results(scopes::SearchReplyProxy const &replyProxy,
85 std::vector<click::Application> const &apps,
86 std::string& categoryTemplate);
87 virtual scopes::Category::SCPtr register_category(scopes::SearchReplyProxy const& searchReply,86 virtual scopes::Category::SCPtr register_category(scopes::SearchReplyProxy const& searchReply,
88 std::string const& id,87 std::string const& id,
89 std::string const& title,88 std::string const& title,
9089
=== renamed file 'scope/click/scope.cpp' => 'scope/clickstore/store-scope.cpp'
--- scope/click/scope.cpp 2014-05-27 08:30:21 +0000
+++ scope/clickstore/store-scope.cpp 2014-06-06 00:43:07 +0000
@@ -28,8 +28,8 @@
28 */28 */
2929
30#include <click/qtbridge.h>30#include <click/qtbridge.h>
31#include "scope.h"31#include "store-scope.h"
32#include "query.h"32#include "store-query.h"
33#include <click/preview.h>33#include <click/preview.h>
34#include <click/interface.h>34#include <click/interface.h>
35#include <click/scope_activation.h>35#include <click/scope_activation.h>
3636
=== renamed file 'scope/click/scope.h' => 'scope/clickstore/store-scope.h'
=== modified file 'scope/tests/CMakeLists.txt'
--- scope/tests/CMakeLists.txt 2014-05-26 14:27:31 +0000
+++ scope/tests/CMakeLists.txt 2014-06-06 00:43:07 +0000
@@ -22,7 +22,7 @@
22qt5_use_modules(${CLICKSCOPE_TESTS_TARGET} Core DBus Network Test)22qt5_use_modules(${CLICKSCOPE_TESTS_TARGET} Core DBus Network Test)
2323
24target_link_libraries(${CLICKSCOPE_TESTS_TARGET}24target_link_libraries(${CLICKSCOPE_TESTS_TARGET}
25 ${SCOPE_LIB_UNVERSIONED}25 ${STORE_LIB_UNVERSIONED}
26 ${SCOPE_LIB_NAME}26 ${SCOPE_LIB_NAME}
2727
28 ${UNITY_SCOPES_LDFLAGS}28 ${UNITY_SCOPES_LDFLAGS}
2929
=== modified file 'scope/tests/click_interface_tool/CMakeLists.txt'
--- scope/tests/click_interface_tool/CMakeLists.txt 2014-05-13 19:32:29 +0000
+++ scope/tests/click_interface_tool/CMakeLists.txt 2014-06-06 00:43:07 +0000
@@ -10,5 +10,5 @@
10)10)
1111
12target_link_libraries (${CLICK_INTERFACE_TOOL_TARGET}12target_link_libraries (${CLICK_INTERFACE_TOOL_TARGET}
13 ${SCOPE_LIB_UNVERSIONED}13 ${STORE_LIB_UNVERSIONED}
14)14)
1515
=== modified file 'scope/tests/click_interface_tool/click_interface_tool.cpp'
--- scope/tests/click_interface_tool/click_interface_tool.cpp 2014-05-13 19:32:29 +0000
+++ scope/tests/click_interface_tool/click_interface_tool.cpp 2014-06-06 00:43:07 +0000
@@ -51,8 +51,8 @@
5151
52 QObject::connect(&timer, &QTimer::timeout, [&]() {52 QObject::connect(&timer, &QTimer::timeout, [&]() {
53 ci.get_dotdesktop_filename(std::string(argv[1]),53 ci.get_dotdesktop_filename(std::string(argv[1]),
54 [&a] (std::string val, click::ManifestError error){54 [&a] (std::string val, click::InterfaceError error){
55 if (error == click::ManifestError::NoError) {55 if (error == click::InterfaceError::NoError) {
56 std::cout << " Success, got dotdesktop:" << val << std::endl;56 std::cout << " Success, got dotdesktop:" << val << std::endl;
57 } else {57 } else {
58 std::cout << " Error:" << val << std::endl;58 std::cout << " Error:" << val << std::endl;
5959
=== modified file 'scope/tests/download_manager_tool/CMakeLists.txt'
--- scope/tests/download_manager_tool/CMakeLists.txt 2014-02-27 17:24:07 +0000
+++ scope/tests/download_manager_tool/CMakeLists.txt 2014-06-06 00:43:07 +0000
@@ -10,5 +10,5 @@
10)10)
1111
12target_link_libraries (${DOWNLOAD_MANAGER_TOOL_TARGET}12target_link_libraries (${DOWNLOAD_MANAGER_TOOL_TARGET}
13 ${SCOPE_LIB_UNVERSIONED}13 ${STORE_LIB_UNVERSIONED}
14)14)
1515
=== modified file 'scope/tests/integration/CMakeLists.txt'
--- scope/tests/integration/CMakeLists.txt 2014-02-27 17:24:07 +0000
+++ scope/tests/integration/CMakeLists.txt 2014-06-06 00:43:07 +0000
@@ -17,7 +17,7 @@
17qt5_use_modules(${INTEGRATION_TARGET} Core DBus Network Test)17qt5_use_modules(${INTEGRATION_TARGET} Core DBus Network Test)
1818
19target_link_libraries (${INTEGRATION_TARGET}19target_link_libraries (${INTEGRATION_TARGET}
20 ${SCOPE_LIB_UNVERSIONED}20 ${STORE_LIB_UNVERSIONED}
2121
22 gmock22 gmock
23 gmock_main23 gmock_main
2424
=== modified file 'scope/tests/test_query.cpp'
--- scope/tests/test_query.cpp 2014-05-21 13:42:45 +0000
+++ scope/tests/test_query.cpp 2014-06-06 00:43:07 +0000
@@ -34,7 +34,7 @@
34#include <gmock/gmock.h>34#include <gmock/gmock.h>
3535
36#include "click/qtbridge.h"36#include "click/qtbridge.h"
37#include "click/query.h"37#include "clickstore/store-query.h"
38#include "click/index.h"38#include "click/index.h"
39#include "click/application.h"39#include "click/application.h"
4040
@@ -47,6 +47,7 @@
47#include <unity/scopes/SearchReply.h>47#include <unity/scopes/SearchReply.h>
4848
49using namespace ::testing;49using namespace ::testing;
50using namespace click;
5051
51namespace52namespace
52{53{
@@ -98,18 +99,20 @@
9899
99 }100 }
100 void wrap_add_available_apps(const scopes::SearchReplyProxy &searchReply,101 void wrap_add_available_apps(const scopes::SearchReplyProxy &searchReply,
101 const std::set<std::string> &locallyInstalledApps,102 const PackageNames &installedPackages,
102 const std::string& categoryTemplate)103 const std::string& categoryTemplate)
103 {104 {
104 add_available_apps(searchReply, locallyInstalledApps, categoryTemplate);105 add_available_apps(searchReply, installedPackages, categoryTemplate);
105 }106 }
106 MOCK_METHOD2(push_result, bool(scopes::SearchReplyProxy const&, scopes::CategorisedResult const&));107 MOCK_METHOD2(push_result, bool(scopes::SearchReplyProxy const&, scopes::CategorisedResult const&));
108 MOCK_METHOD0(clickInterfaceInstance, click::Interface&());
107 MOCK_METHOD1(finished, void(scopes::SearchReplyProxy const&));109 MOCK_METHOD1(finished, void(scopes::SearchReplyProxy const&));
108 MOCK_METHOD5(register_category, scopes::Category::SCPtr(const scopes::SearchReplyProxy &searchReply,110 MOCK_METHOD5(register_category, scopes::Category::SCPtr(const scopes::SearchReplyProxy &searchReply,
109 const std::string &id,111 const std::string &id,
110 const std::string &title,112 const std::string &title,
111 const std::string &icon,113 const std::string &icon,
112 const scopes::CategoryRenderer &renderer_template));114 const scopes::CategoryRenderer &renderer_template));
115 using click::Query::get_installed_packages; // allow tests to access protected method
113};116};
114117
115class MockQueryRun : public MockQueryBase {118class MockQueryRun : public MockQueryBase {
@@ -121,11 +124,12 @@
121 }124 }
122 MOCK_METHOD3(add_available_apps,125 MOCK_METHOD3(add_available_apps,
123 void(scopes::SearchReplyProxy const&searchReply,126 void(scopes::SearchReplyProxy const&searchReply,
124 const std::set<std::string> &locallyInstalledApps,127 const PackageNames &locallyInstalledApps,
125 const std::string& categoryTemplate));128 const std::string& categoryTemplate));
126 MOCK_METHOD3(push_local_results, void(scopes::SearchReplyProxy const &replyProxy,129 MOCK_METHOD3(push_local_results, void(scopes::SearchReplyProxy const &replyProxy,
127 std::vector<click::Application> const &apps,130 std::vector<click::Application> const &apps,
128 std::string& categoryTemplate));131 std::string& categoryTemplate));
132 MOCK_METHOD0(get_installed_packages, PackageNames());
129};133};
130134
131class FakeCategory : public scopes::Category135class FakeCategory : public scopes::Category
@@ -144,7 +148,7 @@
144{148{
145 MockIndex mock_index;149 MockIndex mock_index;
146 scopes::SearchMetadata metadata("en_EN", "phone");150 scopes::SearchMetadata metadata("en_EN", "phone");
147 std::set<std::string> no_installed_packages;151 PackageNames no_installed_packages;
148 const unity::scopes::CannedQuery query("foo.scope", FAKE_QUERY, "");152 const unity::scopes::CannedQuery query("foo.scope", FAKE_QUERY, "");
149 MockQuery q(query, mock_index, metadata);153 MockQuery q(query, mock_index, metadata);
150 EXPECT_CALL(mock_index, do_search(FAKE_QUERY, _)).Times(1);154 EXPECT_CALL(mock_index, do_search(FAKE_QUERY, _)).Times(1);
@@ -163,7 +167,7 @@
163 };167 };
164 MockIndex mock_index(packages);168 MockIndex mock_index(packages);
165 scopes::SearchMetadata metadata("en_EN", "phone");169 scopes::SearchMetadata metadata("en_EN", "phone");
166 std::set<std::string> no_installed_packages;170 PackageNames no_installed_packages;
167 const unity::scopes::CannedQuery query("foo.scope", FAKE_QUERY, "");171 const unity::scopes::CannedQuery query("foo.scope", FAKE_QUERY, "");
168 MockQuery q(query, mock_index, metadata);172 MockQuery q(query, mock_index, metadata);
169 EXPECT_CALL(mock_index, do_search(FAKE_QUERY, _));173 EXPECT_CALL(mock_index, do_search(FAKE_QUERY, _));
@@ -185,7 +189,7 @@
185 };189 };
186 MockIndex mock_index(packages);190 MockIndex mock_index(packages);
187 scopes::SearchMetadata metadata("en_EN", "phone");191 scopes::SearchMetadata metadata("en_EN", "phone");
188 std::set<std::string> no_installed_packages;192 PackageNames no_installed_packages;
189 const unity::scopes::CannedQuery query("foo.scope", FAKE_QUERY, "");193 const unity::scopes::CannedQuery query("foo.scope", FAKE_QUERY, "");
190 MockQuery q(query, mock_index, metadata);194 MockQuery q(query, mock_index, metadata);
191 EXPECT_CALL(mock_index, do_search(FAKE_QUERY, _));195 EXPECT_CALL(mock_index, do_search(FAKE_QUERY, _));
@@ -206,7 +210,7 @@
206 };210 };
207 MockIndex mock_index(packages);211 MockIndex mock_index(packages);
208 scopes::SearchMetadata metadata("en_EN", "phone");212 scopes::SearchMetadata metadata("en_EN", "phone");
209 std::set<std::string> no_installed_packages;213 PackageNames no_installed_packages;
210 const unity::scopes::CannedQuery query("foo.scope", FAKE_QUERY, "");214 const unity::scopes::CannedQuery query("foo.scope", FAKE_QUERY, "");
211 MockQuery q(query, mock_index, metadata);215 MockQuery q(query, mock_index, metadata);
212 EXPECT_CALL(mock_index, do_search(FAKE_QUERY, _)).Times(0);216 EXPECT_CALL(mock_index, do_search(FAKE_QUERY, _)).Times(0);
@@ -225,39 +229,94 @@
225 };229 };
226 MockIndex mock_index(packages);230 MockIndex mock_index(packages);
227 scopes::SearchMetadata metadata("en_EN", "phone");231 scopes::SearchMetadata metadata("en_EN", "phone");
228 std::set<std::string> no_installed_packages;232 PackageNames no_installed_packages;
229 const unity::scopes::CannedQuery query("foo.scope", FAKE_QUERY, "");233 const unity::scopes::CannedQuery query("foo.scope", FAKE_QUERY, "");
230 MockQueryRun q(query, mock_index, metadata);234 MockQueryRun q(query, mock_index, metadata);
231 auto reply = scopes::SearchReplyProxy();235 auto reply = scopes::SearchReplyProxy();
232 EXPECT_CALL(q, push_local_results(_, _, _));236 EXPECT_CALL(q, get_installed_packages()).WillOnce(Return(no_installed_packages));
233 EXPECT_CALL(q, add_available_apps(reply, no_installed_packages, _));237 EXPECT_CALL(q, add_available_apps(reply, no_installed_packages, _));
234238
235 q.run(reply);239 q.run(reply);
236}240}
237241
238MATCHER_P(HasPackageName, n, "") { return arg[click::Query::ResultKeys::NAME].get_string() == n; }242MATCHER_P(HasPackageName, n, "") { return arg[click::Query::ResultKeys::NAME].get_string() == n; }
239243MATCHER_P(IsInstalled, b, "") { return arg[click::Query::ResultKeys::INSTALLED].get_bool() == b; }
240TEST(QueryTest, testDuplicatesFilteredOnPackageName)244
241{245TEST(QueryTest, testDuplicatesNotFilteredAnymore)
242 click::PackageList packages {246{
243 {"org.example.app1", "app title1", 0.0, "icon", "uri"},247 click::PackageList packages {
244 {"org.example.app2", "app title2", 0.0, "icon", "uri"}248 {"org.example.app1", "app title1", 0.0, "icon", "uri"},
245 };249 {"org.example.app2", "app title2", 0.0, "icon", "uri"}
246 MockIndex mock_index(packages);250 };
247 scopes::SearchMetadata metadata("en_EN", "phone");251 MockIndex mock_index(packages);
248 std::set<std::string> one_installed_package {252 scopes::SearchMetadata metadata("en_EN", "phone");
249 "org.example.app2"253 PackageNames one_installed_package {
250 };254 "org.example.app2"
251 const unity::scopes::CannedQuery query("foo.scope", FAKE_QUERY, "");255 };
252 MockQuery q(query, mock_index, metadata);256 const unity::scopes::CannedQuery query("foo.scope", FAKE_QUERY, "");
253 EXPECT_CALL(mock_index, do_search(FAKE_QUERY, _));257 MockQuery q(query, mock_index, metadata);
254258 EXPECT_CALL(mock_index, do_search(FAKE_QUERY, _));
255 scopes::CategoryRenderer renderer("{}");259
256 auto ptrCat = std::make_shared<FakeCategory>("id", "", "", renderer);260 scopes::CategoryRenderer renderer("{}");
257 EXPECT_CALL(q, register_category(_, _, _, _, _)).WillOnce(Return(ptrCat));261 auto ptrCat = std::make_shared<FakeCategory>("id", "", "", renderer);
258262 EXPECT_CALL(q, register_category(_, _, _, _, _)).WillOnce(Return(ptrCat));
259 scopes::SearchReplyProxy reply;263
260 auto expected_name = packages.front().name;264 scopes::SearchReplyProxy reply;
261 EXPECT_CALL(q, push_result(_, HasPackageName(expected_name)));265 auto expected_name1 = packages.front().name;
262 q.wrap_add_available_apps(reply, one_installed_package, FAKE_CATEGORY_TEMPLATE);266 EXPECT_CALL(q, push_result(_, HasPackageName(expected_name1)));
267 auto expected_name2 = packages.back().name;
268 EXPECT_CALL(q, push_result(_, HasPackageName(expected_name2)));
269 q.wrap_add_available_apps(reply, one_installed_package, FAKE_CATEGORY_TEMPLATE);
270}
271
272TEST(QueryTest, testInstalledPackagesFlaggedAsSuch)
273{
274 click::PackageList packages {
275 {"org.example.app1", "app title1", 0.0, "icon", "uri"},
276 {"org.example.app2", "app title2", 0.0, "icon", "uri"}
277 };
278 MockIndex mock_index(packages);
279 scopes::SearchMetadata metadata("en_EN", "phone");
280 PackageNames one_installed_package {
281 "org.example.app2"
282 };
283 const unity::scopes::CannedQuery query("foo.scope", FAKE_QUERY, "");
284 MockQuery q(query, mock_index, metadata);
285 EXPECT_CALL(mock_index, do_search(FAKE_QUERY, _));
286
287 scopes::CategoryRenderer renderer("{}");
288 auto ptrCat = std::make_shared<FakeCategory>("id", "", "", renderer);
289 EXPECT_CALL(q, register_category(_, _, _, _, _)).WillOnce(Return(ptrCat));
290
291 scopes::SearchReplyProxy reply;
292 EXPECT_CALL(q, push_result(_, IsInstalled(true)));
293 EXPECT_CALL(q, push_result(_, IsInstalled(false)));
294 q.wrap_add_available_apps(reply, one_installed_package, FAKE_CATEGORY_TEMPLATE);
295}
296
297class FakeInterface : public click::Interface
298{
299public:
300 MOCK_METHOD1(get_installed_packagenames, void(std::function<void(PackageNames, click::InterfaceError)> callback));
301};
302
303TEST(QueryTest, testGetInstalledPackages)
304{
305 click::PackageList uninstalled_packages {
306 {"name", "title", 0.0, "icon", "uri"}
307 };
308 MockIndex mock_index(uninstalled_packages);
309 scopes::SearchMetadata metadata("en_EN", "phone");
310 const unity::scopes::CannedQuery query("foo.scope", FAKE_QUERY, "");
311 MockQuery q(query, mock_index, metadata);
312 PackageNames installed_packages{"package_1"};
313
314 FakeInterface fake_interface;
315 EXPECT_CALL(q, clickInterfaceInstance()).WillOnce(ReturnRef(fake_interface));
316 EXPECT_CALL(fake_interface, get_installed_packagenames(_)).WillOnce(Invoke(
317 [&](std::function<void(PackageNames, click::InterfaceError)> callback){
318 callback(installed_packages, click::InterfaceError::NoError);
319 }));
320
321 ASSERT_EQ(q.get_installed_packages(), installed_packages);
263}322}

Subscribers

People subscribed via source and target branches

to all changes: