Merge lp:~stolowski/unity-scope-click/no-empty-departments into lp:unity-scope-click/devel

Proposed by Paweł Stołowski
Status: Merged
Approved by: Ted Gould
Approved revision: 401
Merged at revision: 407
Proposed branch: lp:~stolowski/unity-scope-click/no-empty-departments
Merge into: lp:unity-scope-click/devel
Diff against target: 517 lines (+217/-34)
9 files modified
libclickscope/click/application.h (+5/-2)
libclickscope/click/departments-db.cpp (+60/-4)
libclickscope/click/departments-db.h (+7/-1)
libclickscope/click/interface.cpp (+32/-5)
libclickscope/tests/test_departments-db.cpp (+34/-2)
scope/clickapps/apps-query.cpp (+55/-13)
scope/clickapps/apps-query.h (+1/-1)
scope/tests/test_apps_query.cpp (+21/-6)
scope/tests/test_helpers.h (+2/-0)
To merge this branch: bzr merge lp:~stolowski/unity-scope-click/no-empty-departments
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Approve
Ted Gould (community) Approve
dobey (community) Approve
Review via email: mp+230077@code.launchpad.net

Commit message

Exclude empty departments from the departments tree in Apps.

Description of the change

Exclude empty departments from the departments tree in Apps.

When building and filtering the list of installed apps in find_installed_apps, set a real_department attribute of every app. That attribute is later used when populating departments to create a helper lookup of all non-empty subdepartments of current department.

Note: due to a bug in shell plugin https://bugs.launchpad.net/unity-scopes-shell/+bug/1354362 department doesn't disappear when scopes stops returning it (so, after removing last application from a department, an emmpty department stays until reboot).

To post a comment you must log in.
398. By Paweł Stołowski

Minor test updates.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
399. By Paweł Stołowski

Make methods virtual.

400. By Paweł Stołowski

Enhance the test to use an app that is deeper in the departments hierarchy.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
401. By Paweł Stołowski

Merged devel.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
dobey (dobey) :
review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Ted Gould (ted) wrote :

Minor comment. Not sure I understand the SQL but as a backup reviewer it should be fine.

review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) :
review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'libclickscope/click/application.h'
--- libclickscope/click/application.h 2014-07-18 10:35:52 +0000
+++ libclickscope/click/application.h 2014-08-12 10:55:35 +0000
@@ -43,11 +43,13 @@
43 std::string url,43 std::string url,
44 std::string description,44 std::string description,
45 std::string main_screenshot,45 std::string main_screenshot,
46 std::string default_department46 std::string default_department,
47 std::string real_department = ""
47 ) : Package {name, title, price, icon_url, url},48 ) : Package {name, title, price, icon_url, url},
48 description(description),49 description(description),
49 main_screenshot(main_screenshot),50 main_screenshot(main_screenshot),
50 default_department(default_department)51 default_department(default_department),
52 real_department(real_department)
51 {53 {
5254
53 }55 }
@@ -58,6 +60,7 @@
58 std::vector<std::string> keywords;60 std::vector<std::string> keywords;
59 std::string main_screenshot;61 std::string main_screenshot;
60 std::string default_department;62 std::string default_department;
63 std::string real_department;
61 time_t installed_time;64 time_t installed_time;
62};65};
6366
6467
=== modified file 'libclickscope/click/departments-db.cpp'
--- libclickscope/click/departments-db.cpp 2014-08-05 14:16:26 +0000
+++ libclickscope/click/departments-db.cpp 2014-08-12 10:55:35 +0000
@@ -81,11 +81,14 @@
81 insert_dept_id_query_.reset(new QSqlQuery(db_));81 insert_dept_id_query_.reset(new QSqlQuery(db_));
82 insert_dept_name_query_.reset(new QSqlQuery(db_));82 insert_dept_name_query_.reset(new QSqlQuery(db_));
83 select_pkgs_by_dept_.reset(new QSqlQuery(db_));83 select_pkgs_by_dept_.reset(new QSqlQuery(db_));
84 select_dept_for_pkg_.reset(new QSqlQuery(db_));
84 select_pkg_by_pkgid_.reset(new QSqlQuery(db_));85 select_pkg_by_pkgid_.reset(new QSqlQuery(db_));
85 select_pkgs_by_dept_recursive_.reset(new QSqlQuery(db_));86 select_pkgs_by_dept_recursive_.reset(new QSqlQuery(db_));
87 select_pkgs_count_in_dept_recursive_.reset(new QSqlQuery(db_));
86 select_parent_dept_.reset(new QSqlQuery(db_));88 select_parent_dept_.reset(new QSqlQuery(db_));
87 select_children_depts_.reset(new QSqlQuery(db_));89 select_children_depts_.reset(new QSqlQuery(db_));
88 select_dept_name_.reset(new QSqlQuery(db_));90 select_dept_name_.reset(new QSqlQuery(db_));
91 select_is_descendant_of_dept_.reset(new QSqlQuery(db_));
8992
90 delete_pkgmap_query_->prepare("DELETE FROM pkgmap WHERE pkgid=:pkgid");93 delete_pkgmap_query_->prepare("DELETE FROM pkgmap WHERE pkgid=:pkgid");
91 delete_depts_query_->prepare("DELETE FROM depts");94 delete_depts_query_->prepare("DELETE FROM depts");
@@ -94,11 +97,14 @@
94 insert_dept_id_query_->prepare("INSERT OR REPLACE INTO depts (deptid, parentid) VALUES (:deptid, :parentid)");97 insert_dept_id_query_->prepare("INSERT OR REPLACE INTO depts (deptid, parentid) VALUES (:deptid, :parentid)");
95 insert_dept_name_query_->prepare("INSERT OR REPLACE INTO deptnames (deptid, locale, name) VALUES (:deptid, :locale, :name)");98 insert_dept_name_query_->prepare("INSERT OR REPLACE INTO deptnames (deptid, locale, name) VALUES (:deptid, :locale, :name)");
96 select_pkgs_by_dept_->prepare("SELECT pkgid FROM pkgmap WHERE deptid=:deptid");99 select_pkgs_by_dept_->prepare("SELECT pkgid FROM pkgmap WHERE deptid=:deptid");
97 select_pkgs_by_dept_recursive_->prepare("WITH RECURSIVE recdepts(deptid) AS (SELECT deptid FROM depts WHERE deptid=:deptid UNION SELECT depts.deptid FROM recdepts,depts WHERE recdepts.deptid=depts.parentid) SELECT pkgid FROM pkgmap NATURAL JOIN recdepts");100 select_pkgs_by_dept_recursive_->prepare("WITH RECURSIVE recdepts(deptid) AS (SELECT deptid FROM depts WHERE deptid=:deptid OR parentid=:deptid UNION SELECT depts.deptid FROM recdepts,depts WHERE recdepts.deptid=depts.parentid) SELECT pkgid FROM pkgmap NATURAL JOIN recdepts");
101 select_dept_for_pkg_->prepare("SELECT deptid from pkgmap WHERE pkgid=:pkgid");
102 select_pkgs_count_in_dept_recursive_->prepare("WITH RECURSIVE recdepts(deptid) AS (SELECT deptid FROM depts WHERE deptid=:deptid OR parentid=:deptid UNION SELECT depts.deptid FROM recdepts,depts WHERE recdepts.deptid=depts.parentid) SELECT COUNT(pkgid) FROM pkgmap NATURAL JOIN recdepts");
98 select_pkg_by_pkgid_->prepare("SELECT pkgid FROM pkgmap WHERE pkgid=:pkgid");103 select_pkg_by_pkgid_->prepare("SELECT pkgid FROM pkgmap WHERE pkgid=:pkgid");
99 select_children_depts_->prepare("SELECT deptid,(SELECT COUNT(1) from depts AS inner WHERE inner.parentid=outer.deptid) FROM depts AS outer WHERE parentid=:parentid");104 select_children_depts_->prepare("SELECT deptid,(SELECT COUNT(1) from depts AS inner WHERE inner.parentid=outer.deptid) FROM depts AS outer WHERE parentid=:parentid");
100 select_parent_dept_->prepare("SELECT parentid FROM depts WHERE deptid=:deptid");105 select_parent_dept_->prepare("SELECT parentid FROM depts WHERE deptid=:deptid");
101 select_dept_name_->prepare("SELECT name FROM deptnames WHERE deptid=:deptid AND locale=:locale");106 select_dept_name_->prepare("SELECT name FROM deptnames WHERE deptid=:deptid AND locale=:locale");
107 select_is_descendant_of_dept_->prepare("WITH RECURSIVE recdepts(deptid) AS (SELECT deptid FROM depts WHERE parentid=:parentid UNION SELECT depts.deptid FROM recdepts,depts WHERE recdepts.deptid=depts.parentid) SELECT COUNT(1) FROM recdepts WHERE deptid=:deptid");
102}108}
103109
104DepartmentsDb::~DepartmentsDb()110DepartmentsDb::~DepartmentsDb()
@@ -205,7 +211,6 @@
205211
206std::list<DepartmentsDb::DepartmentInfo> DepartmentsDb::get_children_departments(const std::string& department_id)212std::list<DepartmentsDb::DepartmentInfo> DepartmentsDb::get_children_departments(const std::string& department_id)
207{213{
208 // FIXME: this should only return departments that have results, and set 'has_children' flag on the same basis.
209 select_children_depts_->bindValue(":parentid", QVariant(QString::fromStdString(department_id)));214 select_children_depts_->bindValue(":parentid", QVariant(QString::fromStdString(department_id)));
210 if (!select_children_depts_->exec())215 if (!select_children_depts_->exec())
211 {216 {
@@ -215,14 +220,47 @@
215 std::list<DepartmentInfo> depts;220 std::list<DepartmentInfo> depts;
216 while (select_children_depts_->next())221 while (select_children_depts_->next())
217 {222 {
218 const DepartmentInfo inf(select_children_depts_->value(0).toString().toStdString(), select_children_depts_->value(1).toBool());223 auto const child_id = select_children_depts_->value(0).toString().toStdString();
219 depts.push_back(inf);224 // only return child department if it's not empty
225 if (!is_empty(child_id))
226 {
227 const DepartmentInfo inf(child_id, select_children_depts_->value(1).toBool());
228 depts.push_back(inf);
229 }
220 }230 }
221231
222 select_children_depts_->finish();232 select_children_depts_->finish();
233
223 return depts;234 return depts;
224}235}
225236
237bool DepartmentsDb::is_descendant_of_department(const std::string& department_id, const std::string& parent_department_id)
238{
239 select_is_descendant_of_dept_->bindValue(":deptid", QVariant(QString::fromStdString(department_id)));
240 select_is_descendant_of_dept_->bindValue(":parentid", QVariant(QString::fromStdString(parent_department_id)));
241
242 if (!select_is_descendant_of_dept_->exec() || !select_is_descendant_of_dept_->next())
243 {
244 report_db_error(select_is_descendant_of_dept_->lastError(), "Failed to query for package count of department " + department_id);
245 }
246 auto cnt = select_is_descendant_of_dept_->value(0).toInt();
247 select_is_descendant_of_dept_->finish();
248
249 return cnt > 0;
250}
251
252bool DepartmentsDb::is_empty(const std::string& department_id)
253{
254 select_pkgs_count_in_dept_recursive_->bindValue(":deptid", QVariant(QString::fromStdString(department_id)));
255 if (!select_pkgs_count_in_dept_recursive_->exec() || !select_pkgs_count_in_dept_recursive_->next())
256 {
257 report_db_error(select_pkgs_count_in_dept_recursive_->lastError(), "Failed to query for package count of department " + department_id);
258 }
259 auto cnt = select_pkgs_count_in_dept_recursive_->value(0).toInt();
260 select_pkgs_count_in_dept_recursive_->finish();
261 return cnt == 0;
262}
263
226std::unordered_set<std::string> DepartmentsDb::get_packages_for_department(const std::string& department_id, bool recursive)264std::unordered_set<std::string> DepartmentsDb::get_packages_for_department(const std::string& department_id, bool recursive)
227{265{
228 std::unordered_set<std::string> pkgs;266 std::unordered_set<std::string> pkgs;
@@ -240,6 +278,24 @@
240 return pkgs;278 return pkgs;
241}279}
242280
281std::string DepartmentsDb::get_department_for_package(const std::string& package_id)
282{
283 select_dept_for_pkg_->bindValue(":pkgid", QVariant(QString::fromStdString(package_id)));
284 if (!select_dept_for_pkg_->exec())
285 {
286 report_db_error(select_dept_for_pkg_->lastError(), "Failed to query for department of package " + package_id);
287 }
288 if (!select_dept_for_pkg_->next())
289 {
290 select_dept_for_pkg_->finish();
291 throw std::logic_error("Unknown package '" + package_id + "'");
292 }
293 auto const res = select_dept_for_pkg_->value(0).toString().toStdString();
294 select_dept_for_pkg_->finish();
295 return res;
296
297}
298
243bool DepartmentsDb::has_package(const std::string& package_id)299bool DepartmentsDb::has_package(const std::string& package_id)
244{300{
245 select_pkg_by_pkgid_->bindValue(":pkgid", QVariant(QString::fromStdString(package_id)));301 select_pkg_by_pkgid_->bindValue(":pkgid", QVariant(QString::fromStdString(package_id)));
246302
=== modified file 'libclickscope/click/departments-db.h'
--- libclickscope/click/departments-db.h 2014-07-22 20:07:28 +0000
+++ libclickscope/click/departments-db.h 2014-08-12 10:55:35 +0000
@@ -66,9 +66,12 @@
6666
67 virtual std::string get_department_name(const std::string& department_id, const std::list<std::string>& locales);67 virtual std::string get_department_name(const std::string& department_id, const std::list<std::string>& locales);
68 virtual std::unordered_set<std::string> get_packages_for_department(const std::string& department_id, bool recursive = true);68 virtual std::unordered_set<std::string> get_packages_for_department(const std::string& department_id, bool recursive = true);
69 virtual std::string get_department_for_package(const std::string& package_id);
70 virtual bool is_empty(const std::string& department_id);
69 virtual bool has_package(const std::string& package_id);71 virtual bool has_package(const std::string& package_id);
70 virtual std::string get_parent_department_id(const std::string& department_id);72 virtual std::string get_parent_department_id(const std::string& department_id);
71 virtual std::list<DepartmentInfo> get_children_departments(const std::string& department_id);73 virtual std::list<DepartmentInfo> get_children_departments(const std::string& department_id);
74 virtual bool is_descendant_of_department(const std::string& department_id, const std::string& parent_department_id);
7275
73 virtual void store_package_mapping(const std::string& package_id, const std::string& department_id);76 virtual void store_package_mapping(const std::string& package_id, const std::string& department_id);
74 virtual void store_department_mapping(const std::string& department_id, const std::string& parent_department_id);77 virtual void store_department_mapping(const std::string& department_id, const std::string& parent_department_id);
@@ -79,7 +82,7 @@
79 virtual int package_count() const;82 virtual int package_count() const;
80 virtual int department_name_count() const;83 virtual int department_name_count() const;
8184
82 void store_departments(const click::DepartmentList& depts, const std::string& locale);85 virtual void store_departments(const click::DepartmentList& depts, const std::string& locale);
8386
84 static std::unique_ptr<DepartmentsDb> open(bool create = true);87 static std::unique_ptr<DepartmentsDb> open(bool create = true);
8588
@@ -96,11 +99,14 @@
96 std::unique_ptr<QSqlQuery> insert_dept_id_query_;99 std::unique_ptr<QSqlQuery> insert_dept_id_query_;
97 std::unique_ptr<QSqlQuery> insert_dept_name_query_;100 std::unique_ptr<QSqlQuery> insert_dept_name_query_;
98 std::unique_ptr<QSqlQuery> select_pkgs_by_dept_;101 std::unique_ptr<QSqlQuery> select_pkgs_by_dept_;
102 std::unique_ptr<QSqlQuery> select_dept_for_pkg_;
99 std::unique_ptr<QSqlQuery> select_pkg_by_pkgid_;103 std::unique_ptr<QSqlQuery> select_pkg_by_pkgid_;
100 std::unique_ptr<QSqlQuery> select_pkgs_by_dept_recursive_;104 std::unique_ptr<QSqlQuery> select_pkgs_by_dept_recursive_;
105 std::unique_ptr<QSqlQuery> select_pkgs_count_in_dept_recursive_;
101 std::unique_ptr<QSqlQuery> select_parent_dept_;106 std::unique_ptr<QSqlQuery> select_parent_dept_;
102 std::unique_ptr<QSqlQuery> select_children_depts_;107 std::unique_ptr<QSqlQuery> select_children_depts_;
103 std::unique_ptr<QSqlQuery> select_dept_name_;108 std::unique_ptr<QSqlQuery> select_dept_name_;
109 std::unique_ptr<QSqlQuery> select_is_descendant_of_dept_;
104};110};
105111
106}112}
107113
=== modified file 'libclickscope/click/interface.cpp'
--- libclickscope/click/interface.cpp 2014-07-23 16:22:19 +0000
+++ libclickscope/click/interface.cpp 2014-08-12 10:55:35 +0000
@@ -277,12 +277,13 @@
277 || Interface::is_non_click_app(QString::fromStdString(filename))) {277 || Interface::is_non_click_app(QString::fromStdString(filename))) {
278 auto app = load_app_from_desktop(keyFile, filename);278 auto app = load_app_from_desktop(keyFile, filename);
279279
280 // app from click package has non-empty name; for non-click apps use desktop filename
281 const std::string department_key = app.name.empty() ? filename : app.name;
282
280 // check if apps is present in current department283 // check if apps is present in current department
281 if (apply_department_filter)284 if (apply_department_filter)
282 {285 {
283 // app from click package has non-empty name; for non-click apps use desktop filename286 if (packages_in_department.find(department_key) == packages_in_department.end())
284 const std::string key = app.name.empty() ? filename : app.name;
285 if (packages_in_department.find(key) == packages_in_department.end())
286 {287 {
287 if (app.default_department.empty())288 if (app.default_department.empty())
288 {289 {
@@ -293,7 +294,7 @@
293 {294 {
294 // default department not empty: check if this app is in a different295 // default department not empty: check if this app is in a different
295 // department in the db (i.e. got moved from the default department);296 // department in the db (i.e. got moved from the default department);
296 if (depts_db->has_package(key))297 if (depts_db->has_package(department_key))
297 {298 {
298 // app is now in a different department299 // app is now in a different department
299 return;300 return;
@@ -303,12 +304,38 @@
303 {304 {
304 return;305 return;
305 }306 }
306
307 // else - this package is in current department307 // else - this package is in current department
308 }308 }
309 }309 }
310 }310 }
311311
312 //
313 // the packages_in_department set contains packages from
314 // all its subdepartments; we need to find actual department now
315 // to update app.real_department.
316 if (depts_db)
317 {
318 if (depts_db->has_package(department_key))
319 {
320 try
321 {
322 app.real_department = depts_db->get_department_for_package(department_key);
323 }
324 catch (const std::exception &e)
325 {
326 qWarning() << "Failed to get department of package:" << QString::fromStdString(department_key);
327 }
328 }
329 else
330 {
331 app.real_department = app.default_department;
332 if (app.real_department.empty())
333 {
334 qWarning() << "No default department set in the .desktop file and no entry in the database for" << QString::fromStdString(department_key);
335 }
336 }
337 }
338
312 if (search_query.empty()) {339 if (search_query.empty()) {
313 result.push_back(app);340 result.push_back(app);
314 } else {341 } else {
315342
=== modified file 'libclickscope/tests/test_departments-db.cpp'
--- libclickscope/tests/test_departments-db.cpp 2014-08-05 14:16:26 +0000
+++ libclickscope/tests/test_departments-db.cpp 2014-08-12 10:55:35 +0000
@@ -53,10 +53,13 @@
53 EXPECT_FALSE(insert_dept_name_query_->isActive());53 EXPECT_FALSE(insert_dept_name_query_->isActive());
54 EXPECT_FALSE(select_pkgs_by_dept_->isActive());54 EXPECT_FALSE(select_pkgs_by_dept_->isActive());
55 EXPECT_FALSE(select_pkgs_by_dept_recursive_->isActive());55 EXPECT_FALSE(select_pkgs_by_dept_recursive_->isActive());
56 EXPECT_FALSE(select_dept_for_pkg_->isActive());
57 EXPECT_FALSE(select_pkgs_count_in_dept_recursive_->isActive());
56 EXPECT_FALSE(select_pkg_by_pkgid_->isActive());58 EXPECT_FALSE(select_pkg_by_pkgid_->isActive());
57 EXPECT_FALSE(select_parent_dept_->isActive());59 EXPECT_FALSE(select_parent_dept_->isActive());
58 EXPECT_FALSE(select_children_depts_->isActive());60 EXPECT_FALSE(select_children_depts_->isActive());
59 EXPECT_FALSE(select_dept_name_->isActive());61 EXPECT_FALSE(select_dept_name_->isActive());
62 EXPECT_FALSE(select_is_descendant_of_dept_->isActive());
60 }63 }
61};64};
6265
@@ -112,6 +115,35 @@
112 }115 }
113}116}
114117
118TEST_F(DepartmentsDbTest, testDepartmentForPackageLookup)
119{
120 EXPECT_EQ("rpg", db->get_department_for_package("game1"));
121 EXPECT_EQ("fps", db->get_department_for_package("game2"));
122 EXPECT_EQ("office", db->get_department_for_package("app2"));
123 EXPECT_EQ("tools", db->get_department_for_package("app1"));
124 EXPECT_THROW(db->get_department_for_package("foobar"), std::logic_error);
125}
126
127TEST_F(DepartmentsDbTest, testIsDepartmentEmpty)
128{
129 EXPECT_TRUE(db->is_empty("card"));
130 EXPECT_FALSE(db->is_empty(""));
131 EXPECT_FALSE(db->is_empty("games"));
132 EXPECT_FALSE(db->is_empty("office"));
133 EXPECT_FALSE(db->is_empty("tools"));
134}
135
136TEST_F(DepartmentsDbTest, testIsDescendantOfDepartment)
137{
138 EXPECT_TRUE(db->is_descendant_of_department("rpg", "games"));
139 EXPECT_TRUE(db->is_descendant_of_department("office", "tools"));
140 EXPECT_TRUE(db->is_descendant_of_department("office", ""));
141 EXPECT_TRUE(db->is_descendant_of_department("rpg", ""));
142 EXPECT_TRUE(db->is_descendant_of_department("games", ""));
143 EXPECT_FALSE(db->is_descendant_of_department("games", "office"));
144 EXPECT_FALSE(db->is_descendant_of_department("", "games"));
145}
146
115TEST_F(DepartmentsDbTest, testDepartmentNameUpdates)147TEST_F(DepartmentsDbTest, testDepartmentNameUpdates)
116{148{
117 {149 {
@@ -156,10 +188,10 @@
156 }188 }
157 {189 {
158 auto depts = db->get_children_departments("games");190 auto depts = db->get_children_departments("games");
159 EXPECT_EQ(3u, depts.size());191 EXPECT_EQ(2u, depts.size());
160 EXPECT_TRUE(std::find(depts.begin(), depts.end(), DepartmentsDb::DepartmentInfo("rpg", false)) != depts.end());192 EXPECT_TRUE(std::find(depts.begin(), depts.end(), DepartmentsDb::DepartmentInfo("rpg", false)) != depts.end());
161 EXPECT_TRUE(std::find(depts.begin(), depts.end(), DepartmentsDb::DepartmentInfo("fps", false)) != depts.end());193 EXPECT_TRUE(std::find(depts.begin(), depts.end(), DepartmentsDb::DepartmentInfo("fps", false)) != depts.end());
162 EXPECT_TRUE(std::find(depts.begin(), depts.end(), DepartmentsDb::DepartmentInfo("card", false)) != depts.end());194 EXPECT_FALSE(std::find(depts.begin(), depts.end(), DepartmentsDb::DepartmentInfo("card", false)) != depts.end());
163 }195 }
164}196}
165197
166198
=== modified file 'scope/clickapps/apps-query.cpp'
--- scope/clickapps/apps-query.cpp 2014-08-06 17:30:55 +0000
+++ scope/clickapps/apps-query.cpp 2014-08-12 10:55:35 +0000
@@ -291,11 +291,22 @@
291 searchReply->push(res);291 searchReply->push(res);
292}292}
293293
294void click::apps::Query::push_local_departments(scopes::SearchReplyProxy const& replyProxy)294void click::apps::Query::push_local_departments(scopes::SearchReplyProxy const& replyProxy, const std::vector<Application>& apps)
295{295{
296 auto const current_dep_id = query().department_id();296 auto const current_dep_id = query().department_id();
297 const std::list<std::string> locales = { search_metadata().locale(), "en_US" };297 const std::list<std::string> locales = { search_metadata().locale(), "en_US" };
298298
299 //
300 // create helper lookup of all departments of currently installed apps.
301 // note that apps that are passed here are supposed to be already filterd by current department
302 // that means we only have subdepartments of current department (or subdepartment(s) of subdepartment(s)
303 // and so on of current department, as the hierarchy may be of arbitrary depth.
304 std::unordered_set<std::string> all_subdepartments;
305 for (auto const app: apps)
306 {
307 all_subdepartments.insert(app.real_department);
308 }
309
299 unity::scopes::Department::SPtr root;310 unity::scopes::Department::SPtr root;
300311
301 try312 try
@@ -309,17 +320,48 @@
309 // attach subdepartments to it320 // attach subdepartments to it
310 for (auto const& subdep: impl->depts_db->get_children_departments(current_dep_id))321 for (auto const& subdep: impl->depts_db->get_children_departments(current_dep_id))
311 {322 {
312 // if single supdepartment fails, then ignore it and continue with others323 //
313 try324 // check if this subdepartment either directly matches a subdepartment of installed app,
314 {325 // or is any of the departments of installed apps is a descendant of current subdepartment.
315 name = impl->depts_db->get_department_name(subdep.id, locales);326 // the latter means we have app somewhere in the subtree of the current subdepartment, so it
316 unity::scopes::Department::SPtr dep = unity::scopes::Department::create(subdep.id, query(), name);327 // needs to be shown.
317 dep->set_has_subdepartments(subdep.has_children);328 bool show_subdepartment = false;
318 current->add_subdepartment(dep);329 auto it = all_subdepartments.find(subdep.id);
319 }330 if (it != all_subdepartments.end())
320 catch (const std::exception &e)331 {
321 {332 // subdepartment id matches directly one of the ids from all_subdepartments
322 qWarning() << "Failed to create subdeparment:" << QString::fromStdString(e.what());333 show_subdepartment = true;
334 all_subdepartments.erase(it);
335 }
336 else
337 {
338 // no direct match - we need to check descendants of this subdepartment
339 // by querying the db
340 for (auto it = all_subdepartments.begin(); it != all_subdepartments.end(); it++)
341 {
342 if (impl->depts_db->is_descendant_of_department(*it, subdep.id))
343 {
344 show_subdepartment = true;
345 all_subdepartments.erase(it);
346 break;
347 }
348 }
349 }
350
351 if (show_subdepartment)
352 {
353 // if single supdepartment fails, then ignore it and continue with others
354 try
355 {
356 name = impl->depts_db->get_department_name(subdep.id, locales);
357 unity::scopes::Department::SPtr dep = unity::scopes::Department::create(subdep.id, query(), name);
358 dep->set_has_subdepartments(subdep.has_children);
359 current->add_subdepartment(dep);
360 }
361 catch (const std::exception &e)
362 {
363 qWarning() << "Failed to create subdeparment:" << QString::fromStdString(e.what());
364 }
323 }365 }
324 }366 }
325367
@@ -357,7 +399,7 @@
357 if (querystr.empty()) {399 if (querystr.empty()) {
358 if (impl->depts_db)400 if (impl->depts_db)
359 {401 {
360 push_local_departments(searchReply);402 push_local_departments(searchReply, localResults);
361 }403 }
362 }404 }
363405
364406
=== modified file 'scope/clickapps/apps-query.h'
--- scope/clickapps/apps-query.h 2014-07-22 13:17:28 +0000
+++ scope/clickapps/apps-query.h 2014-08-12 10:55:35 +0000
@@ -74,7 +74,7 @@
7474
75 virtual void add_fake_store_app(scopes::SearchReplyProxy const &replyProxy);75 virtual void add_fake_store_app(scopes::SearchReplyProxy const &replyProxy);
7676
77 virtual void push_local_departments(scopes::SearchReplyProxy const& replyProxy);77 virtual void push_local_departments(scopes::SearchReplyProxy const& replyProxy, const std::vector<Application>& apps);
7878
79protected:79protected:
80 virtual click::Interface& clickInterfaceInstance();80 virtual click::Interface& clickInterfaceInstance();
8181
=== modified file 'scope/tests/test_apps_query.cpp'
--- scope/tests/test_apps_query.cpp 2014-08-05 14:16:26 +0000
+++ scope/tests/test_apps_query.cpp 2014-08-12 10:55:35 +0000
@@ -192,7 +192,10 @@
192192
193class DepartmentsTest : public ::testing::Test {193class DepartmentsTest : public ::testing::Test {
194protected:194protected:
195 const std::vector<click::Application> installed_apps = {{"app1", "App1", 0.0f, "icon", "url", "descr", "scrshot", ""}};195 const std::vector<click::Application> installed_apps = {
196 {"app1", "App1", 0.0f, "icon", "url", "descr", "scrshot", "", "games-rpg"},
197 {"app2", "App2", 0.0f, "icon", "url", "descr", "scrshot", "", "video"}
198 };
196 const scopes::SearchMetadata metadata{"en_EN", "phone"};199 const scopes::SearchMetadata metadata{"en_EN", "phone"};
197 const scopes::CategoryRenderer renderer{"{}"};200 const scopes::CategoryRenderer renderer{"{}"};
198 const std::list<std::string> expected_locales {"en_EN", "en_US"};201 const std::list<std::string> expected_locales {"en_EN", "en_US"};
@@ -214,6 +217,7 @@
214 scopes::testing::MockSearchReply mock_reply;217 scopes::testing::MockSearchReply mock_reply;
215 scopes::SearchReplyProxy reply(&mock_reply, [](unity::scopes::SearchReply*){});218 scopes::SearchReplyProxy reply(&mock_reply, [](unity::scopes::SearchReply*){});
216219
220 // no apps in 'books' department, thus excluded
217 std::list<std::string> expected_departments({{"", "games", "video"}});221 std::list<std::string> expected_departments({{"", "games", "video"}});
218222
219 EXPECT_CALL(*clickif, find_installed_apps(_, _, _)).WillOnce(Return(installed_apps));223 EXPECT_CALL(*clickif, find_installed_apps(_, _, _)).WillOnce(Return(installed_apps));
@@ -222,14 +226,25 @@
222 EXPECT_CALL(mock_reply, register_category("store", _, _, _)).WillOnce(Return(ptrCat));226 EXPECT_CALL(mock_reply, register_category("store", _, _, _)).WillOnce(Return(ptrCat));
223 EXPECT_CALL(mock_reply, register_departments(MatchesDepartments(expected_departments)));227 EXPECT_CALL(mock_reply, register_departments(MatchesDepartments(expected_departments)));
224228
225 EXPECT_CALL(mock_reply, push(Matcher<unity::scopes::CategorisedResult const&>(_))).Times(2).WillRepeatedly(Return(true));229 EXPECT_CALL(mock_reply, push(Matcher<unity::scopes::CategorisedResult const&>(_))).Times(3).WillRepeatedly(Return(true));
230
231 ON_CALL(*depts_db, is_descendant_of_department(_, _)).WillByDefault(Return(false));
232 ON_CALL(*depts_db, is_descendant_of_department("games", "")).WillByDefault(Return(true));
233 ON_CALL(*depts_db, is_descendant_of_department("games-rpg", "games")).WillByDefault(Return(true));
234 ON_CALL(*depts_db, is_descendant_of_department("books", "")).WillByDefault(Return(true));
235 ON_CALL(*depts_db, is_descendant_of_department("video", "")).WillByDefault(Return(true));
226236
227 EXPECT_CALL(*depts_db, get_department_name("games", expected_locales)).WillOnce(Return("Games"));237 EXPECT_CALL(*depts_db, get_department_name("games", expected_locales)).WillOnce(Return("Games"));
228 EXPECT_CALL(*depts_db, get_department_name("video", expected_locales)).WillOnce(Return("Video"));238 EXPECT_CALL(*depts_db, get_department_name("video", expected_locales)).WillOnce(Return("Video"));
239 EXPECT_CALL(*depts_db, is_empty("games")).WillRepeatedly(Return(false));
240 EXPECT_CALL(*depts_db, is_empty("video")).WillRepeatedly(Return(false));
241 EXPECT_CALL(*depts_db, is_empty("books")).WillRepeatedly(Return(false));
242 EXPECT_CALL(*depts_db, is_descendant_of_department(_, _)).Times(AnyNumber());
229 EXPECT_CALL(*depts_db, get_children_departments("")).WillOnce(Return(243 EXPECT_CALL(*depts_db, get_children_departments("")).WillOnce(Return(
230 std::list<click::DepartmentsDb::DepartmentInfo>({244 std::list<click::DepartmentsDb::DepartmentInfo>({
231 {"games", false},245 {"games", true},
232 {"video", true}246 {"video", true},
247 {"books", true}
233 }))248 }))
234 );249 );
235250
@@ -259,7 +274,7 @@
259 EXPECT_CALL(mock_reply, register_category("store", _, _, _)).WillOnce(Return(ptrCat));274 EXPECT_CALL(mock_reply, register_category("store", _, _, _)).WillOnce(Return(ptrCat));
260 EXPECT_CALL(mock_reply, register_departments(MatchesDepartments(expected_departments)));275 EXPECT_CALL(mock_reply, register_departments(MatchesDepartments(expected_departments)));
261276
262 EXPECT_CALL(mock_reply, push(Matcher<unity::scopes::CategorisedResult const&>(_))).Times(2).WillRepeatedly(Return(true));277 EXPECT_CALL(mock_reply, push(Matcher<unity::scopes::CategorisedResult const&>(_))).Times(3).WillRepeatedly(Return(true));
263278
264 EXPECT_CALL(*depts_db, get_parent_department_id("games")).WillOnce(Return(""));279 EXPECT_CALL(*depts_db, get_parent_department_id("games")).WillOnce(Return(""));
265 EXPECT_CALL(*depts_db, get_department_name("games", expected_locales)).WillOnce(Return("Games"));280 EXPECT_CALL(*depts_db, get_department_name("games", expected_locales)).WillOnce(Return("Games"));
@@ -290,7 +305,7 @@
290 EXPECT_CALL(mock_reply, register_category("local", StrEq(""), _, _)).WillOnce(Return(ptrCat));305 EXPECT_CALL(mock_reply, register_category("local", StrEq(""), _, _)).WillOnce(Return(ptrCat));
291 EXPECT_CALL(mock_reply, register_category("store", _, _, _)).WillOnce(Return(ptrCat));306 EXPECT_CALL(mock_reply, register_category("store", _, _, _)).WillOnce(Return(ptrCat));
292307
293 EXPECT_CALL(mock_reply, push(Matcher<unity::scopes::CategorisedResult const&>(_))).Times(2).WillRepeatedly(Return(true));308 EXPECT_CALL(mock_reply, push(Matcher<unity::scopes::CategorisedResult const&>(_))).Times(3).WillRepeatedly(Return(true));
294309
295 q.run(reply);310 q.run(reply);
296 }311 }
297312
=== modified file 'scope/tests/test_helpers.h'
--- scope/tests/test_helpers.h 2014-07-18 15:01:41 +0000
+++ scope/tests/test_helpers.h 2014-08-12 10:55:35 +0000
@@ -65,6 +65,8 @@
65 MOCK_METHOD2(get_packages_for_department, std::unordered_set<std::string>(const std::string&, bool));65 MOCK_METHOD2(get_packages_for_department, std::unordered_set<std::string>(const std::string&, bool));
66 MOCK_METHOD1(get_parent_department_id, std::string(const std::string&));66 MOCK_METHOD1(get_parent_department_id, std::string(const std::string&));
67 MOCK_METHOD1(get_children_departments, std::list<click::DepartmentsDb::DepartmentInfo>(const std::string&));67 MOCK_METHOD1(get_children_departments, std::list<click::DepartmentsDb::DepartmentInfo>(const std::string&));
68 MOCK_METHOD1(is_empty, bool(const std::string&));
69 MOCK_METHOD2(is_descendant_of_department, bool(const std::string&, const std::string&));
6870
69 MOCK_METHOD2(store_package_mapping, void(const std::string&, const std::string&));71 MOCK_METHOD2(store_package_mapping, void(const std::string&, const std::string&));
70 MOCK_METHOD2(store_department_mapping, void(const std::string&, const std::string&));72 MOCK_METHOD2(store_department_mapping, void(const std::string&, const std::string&));

Subscribers

People subscribed via source and target branches

to all changes: