Merge lp:~stolowski/unity-scope-click/no-empty-departments into lp:unity-scope-click/devel
- no-empty-departments
- Merge into devel
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 | ||||
Related bugs: |
|
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_
Note: due to a bug in shell plugin https:/
- 398. By Paweł Stołowski
-
Minor test updates.
PS Jenkins bot (ps-jenkins) wrote : | # |
- 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.
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:398
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:400
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 401. By Paweł Stołowski
-
Merged devel.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:401
http://
Executed test runs:
SUCCESS: http://
FAILURE: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
dobey (dobey) : | # |
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:401
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
Ted Gould (ted) wrote : | # |
Minor comment. Not sure I understand the SQL but as a backup reviewer it should be fine.
PS Jenkins bot (ps-jenkins) : | # |
Preview Diff
1 | === modified file 'libclickscope/click/application.h' |
2 | --- libclickscope/click/application.h 2014-07-18 10:35:52 +0000 |
3 | +++ libclickscope/click/application.h 2014-08-12 10:55:35 +0000 |
4 | @@ -43,11 +43,13 @@ |
5 | std::string url, |
6 | std::string description, |
7 | std::string main_screenshot, |
8 | - std::string default_department |
9 | + std::string default_department, |
10 | + std::string real_department = "" |
11 | ) : Package {name, title, price, icon_url, url}, |
12 | description(description), |
13 | main_screenshot(main_screenshot), |
14 | - default_department(default_department) |
15 | + default_department(default_department), |
16 | + real_department(real_department) |
17 | { |
18 | |
19 | } |
20 | @@ -58,6 +60,7 @@ |
21 | std::vector<std::string> keywords; |
22 | std::string main_screenshot; |
23 | std::string default_department; |
24 | + std::string real_department; |
25 | time_t installed_time; |
26 | }; |
27 | |
28 | |
29 | === modified file 'libclickscope/click/departments-db.cpp' |
30 | --- libclickscope/click/departments-db.cpp 2014-08-05 14:16:26 +0000 |
31 | +++ libclickscope/click/departments-db.cpp 2014-08-12 10:55:35 +0000 |
32 | @@ -81,11 +81,14 @@ |
33 | insert_dept_id_query_.reset(new QSqlQuery(db_)); |
34 | insert_dept_name_query_.reset(new QSqlQuery(db_)); |
35 | select_pkgs_by_dept_.reset(new QSqlQuery(db_)); |
36 | + select_dept_for_pkg_.reset(new QSqlQuery(db_)); |
37 | select_pkg_by_pkgid_.reset(new QSqlQuery(db_)); |
38 | select_pkgs_by_dept_recursive_.reset(new QSqlQuery(db_)); |
39 | + select_pkgs_count_in_dept_recursive_.reset(new QSqlQuery(db_)); |
40 | select_parent_dept_.reset(new QSqlQuery(db_)); |
41 | select_children_depts_.reset(new QSqlQuery(db_)); |
42 | select_dept_name_.reset(new QSqlQuery(db_)); |
43 | + select_is_descendant_of_dept_.reset(new QSqlQuery(db_)); |
44 | |
45 | delete_pkgmap_query_->prepare("DELETE FROM pkgmap WHERE pkgid=:pkgid"); |
46 | delete_depts_query_->prepare("DELETE FROM depts"); |
47 | @@ -94,11 +97,14 @@ |
48 | insert_dept_id_query_->prepare("INSERT OR REPLACE INTO depts (deptid, parentid) VALUES (:deptid, :parentid)"); |
49 | insert_dept_name_query_->prepare("INSERT OR REPLACE INTO deptnames (deptid, locale, name) VALUES (:deptid, :locale, :name)"); |
50 | select_pkgs_by_dept_->prepare("SELECT pkgid FROM pkgmap WHERE deptid=:deptid"); |
51 | - 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"); |
52 | + 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"); |
53 | + select_dept_for_pkg_->prepare("SELECT deptid from pkgmap WHERE pkgid=:pkgid"); |
54 | + 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"); |
55 | select_pkg_by_pkgid_->prepare("SELECT pkgid FROM pkgmap WHERE pkgid=:pkgid"); |
56 | 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"); |
57 | select_parent_dept_->prepare("SELECT parentid FROM depts WHERE deptid=:deptid"); |
58 | select_dept_name_->prepare("SELECT name FROM deptnames WHERE deptid=:deptid AND locale=:locale"); |
59 | + 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"); |
60 | } |
61 | |
62 | DepartmentsDb::~DepartmentsDb() |
63 | @@ -205,7 +211,6 @@ |
64 | |
65 | std::list<DepartmentsDb::DepartmentInfo> DepartmentsDb::get_children_departments(const std::string& department_id) |
66 | { |
67 | - // FIXME: this should only return departments that have results, and set 'has_children' flag on the same basis. |
68 | select_children_depts_->bindValue(":parentid", QVariant(QString::fromStdString(department_id))); |
69 | if (!select_children_depts_->exec()) |
70 | { |
71 | @@ -215,14 +220,47 @@ |
72 | std::list<DepartmentInfo> depts; |
73 | while (select_children_depts_->next()) |
74 | { |
75 | - const DepartmentInfo inf(select_children_depts_->value(0).toString().toStdString(), select_children_depts_->value(1).toBool()); |
76 | - depts.push_back(inf); |
77 | + auto const child_id = select_children_depts_->value(0).toString().toStdString(); |
78 | + // only return child department if it's not empty |
79 | + if (!is_empty(child_id)) |
80 | + { |
81 | + const DepartmentInfo inf(child_id, select_children_depts_->value(1).toBool()); |
82 | + depts.push_back(inf); |
83 | + } |
84 | } |
85 | |
86 | select_children_depts_->finish(); |
87 | + |
88 | return depts; |
89 | } |
90 | |
91 | +bool DepartmentsDb::is_descendant_of_department(const std::string& department_id, const std::string& parent_department_id) |
92 | +{ |
93 | + select_is_descendant_of_dept_->bindValue(":deptid", QVariant(QString::fromStdString(department_id))); |
94 | + select_is_descendant_of_dept_->bindValue(":parentid", QVariant(QString::fromStdString(parent_department_id))); |
95 | + |
96 | + if (!select_is_descendant_of_dept_->exec() || !select_is_descendant_of_dept_->next()) |
97 | + { |
98 | + report_db_error(select_is_descendant_of_dept_->lastError(), "Failed to query for package count of department " + department_id); |
99 | + } |
100 | + auto cnt = select_is_descendant_of_dept_->value(0).toInt(); |
101 | + select_is_descendant_of_dept_->finish(); |
102 | + |
103 | + return cnt > 0; |
104 | +} |
105 | + |
106 | +bool DepartmentsDb::is_empty(const std::string& department_id) |
107 | +{ |
108 | + select_pkgs_count_in_dept_recursive_->bindValue(":deptid", QVariant(QString::fromStdString(department_id))); |
109 | + if (!select_pkgs_count_in_dept_recursive_->exec() || !select_pkgs_count_in_dept_recursive_->next()) |
110 | + { |
111 | + report_db_error(select_pkgs_count_in_dept_recursive_->lastError(), "Failed to query for package count of department " + department_id); |
112 | + } |
113 | + auto cnt = select_pkgs_count_in_dept_recursive_->value(0).toInt(); |
114 | + select_pkgs_count_in_dept_recursive_->finish(); |
115 | + return cnt == 0; |
116 | +} |
117 | + |
118 | std::unordered_set<std::string> DepartmentsDb::get_packages_for_department(const std::string& department_id, bool recursive) |
119 | { |
120 | std::unordered_set<std::string> pkgs; |
121 | @@ -240,6 +278,24 @@ |
122 | return pkgs; |
123 | } |
124 | |
125 | +std::string DepartmentsDb::get_department_for_package(const std::string& package_id) |
126 | +{ |
127 | + select_dept_for_pkg_->bindValue(":pkgid", QVariant(QString::fromStdString(package_id))); |
128 | + if (!select_dept_for_pkg_->exec()) |
129 | + { |
130 | + report_db_error(select_dept_for_pkg_->lastError(), "Failed to query for department of package " + package_id); |
131 | + } |
132 | + if (!select_dept_for_pkg_->next()) |
133 | + { |
134 | + select_dept_for_pkg_->finish(); |
135 | + throw std::logic_error("Unknown package '" + package_id + "'"); |
136 | + } |
137 | + auto const res = select_dept_for_pkg_->value(0).toString().toStdString(); |
138 | + select_dept_for_pkg_->finish(); |
139 | + return res; |
140 | + |
141 | +} |
142 | + |
143 | bool DepartmentsDb::has_package(const std::string& package_id) |
144 | { |
145 | select_pkg_by_pkgid_->bindValue(":pkgid", QVariant(QString::fromStdString(package_id))); |
146 | |
147 | === modified file 'libclickscope/click/departments-db.h' |
148 | --- libclickscope/click/departments-db.h 2014-07-22 20:07:28 +0000 |
149 | +++ libclickscope/click/departments-db.h 2014-08-12 10:55:35 +0000 |
150 | @@ -66,9 +66,12 @@ |
151 | |
152 | virtual std::string get_department_name(const std::string& department_id, const std::list<std::string>& locales); |
153 | virtual std::unordered_set<std::string> get_packages_for_department(const std::string& department_id, bool recursive = true); |
154 | + virtual std::string get_department_for_package(const std::string& package_id); |
155 | + virtual bool is_empty(const std::string& department_id); |
156 | virtual bool has_package(const std::string& package_id); |
157 | virtual std::string get_parent_department_id(const std::string& department_id); |
158 | virtual std::list<DepartmentInfo> get_children_departments(const std::string& department_id); |
159 | + virtual bool is_descendant_of_department(const std::string& department_id, const std::string& parent_department_id); |
160 | |
161 | virtual void store_package_mapping(const std::string& package_id, const std::string& department_id); |
162 | virtual void store_department_mapping(const std::string& department_id, const std::string& parent_department_id); |
163 | @@ -79,7 +82,7 @@ |
164 | virtual int package_count() const; |
165 | virtual int department_name_count() const; |
166 | |
167 | - void store_departments(const click::DepartmentList& depts, const std::string& locale); |
168 | + virtual void store_departments(const click::DepartmentList& depts, const std::string& locale); |
169 | |
170 | static std::unique_ptr<DepartmentsDb> open(bool create = true); |
171 | |
172 | @@ -96,11 +99,14 @@ |
173 | std::unique_ptr<QSqlQuery> insert_dept_id_query_; |
174 | std::unique_ptr<QSqlQuery> insert_dept_name_query_; |
175 | std::unique_ptr<QSqlQuery> select_pkgs_by_dept_; |
176 | + std::unique_ptr<QSqlQuery> select_dept_for_pkg_; |
177 | std::unique_ptr<QSqlQuery> select_pkg_by_pkgid_; |
178 | std::unique_ptr<QSqlQuery> select_pkgs_by_dept_recursive_; |
179 | + std::unique_ptr<QSqlQuery> select_pkgs_count_in_dept_recursive_; |
180 | std::unique_ptr<QSqlQuery> select_parent_dept_; |
181 | std::unique_ptr<QSqlQuery> select_children_depts_; |
182 | std::unique_ptr<QSqlQuery> select_dept_name_; |
183 | + std::unique_ptr<QSqlQuery> select_is_descendant_of_dept_; |
184 | }; |
185 | |
186 | } |
187 | |
188 | === modified file 'libclickscope/click/interface.cpp' |
189 | --- libclickscope/click/interface.cpp 2014-07-23 16:22:19 +0000 |
190 | +++ libclickscope/click/interface.cpp 2014-08-12 10:55:35 +0000 |
191 | @@ -277,12 +277,13 @@ |
192 | || Interface::is_non_click_app(QString::fromStdString(filename))) { |
193 | auto app = load_app_from_desktop(keyFile, filename); |
194 | |
195 | + // app from click package has non-empty name; for non-click apps use desktop filename |
196 | + const std::string department_key = app.name.empty() ? filename : app.name; |
197 | + |
198 | // check if apps is present in current department |
199 | if (apply_department_filter) |
200 | { |
201 | - // app from click package has non-empty name; for non-click apps use desktop filename |
202 | - const std::string key = app.name.empty() ? filename : app.name; |
203 | - if (packages_in_department.find(key) == packages_in_department.end()) |
204 | + if (packages_in_department.find(department_key) == packages_in_department.end()) |
205 | { |
206 | if (app.default_department.empty()) |
207 | { |
208 | @@ -293,7 +294,7 @@ |
209 | { |
210 | // default department not empty: check if this app is in a different |
211 | // department in the db (i.e. got moved from the default department); |
212 | - if (depts_db->has_package(key)) |
213 | + if (depts_db->has_package(department_key)) |
214 | { |
215 | // app is now in a different department |
216 | return; |
217 | @@ -303,12 +304,38 @@ |
218 | { |
219 | return; |
220 | } |
221 | - |
222 | // else - this package is in current department |
223 | } |
224 | } |
225 | } |
226 | |
227 | + // |
228 | + // the packages_in_department set contains packages from |
229 | + // all its subdepartments; we need to find actual department now |
230 | + // to update app.real_department. |
231 | + if (depts_db) |
232 | + { |
233 | + if (depts_db->has_package(department_key)) |
234 | + { |
235 | + try |
236 | + { |
237 | + app.real_department = depts_db->get_department_for_package(department_key); |
238 | + } |
239 | + catch (const std::exception &e) |
240 | + { |
241 | + qWarning() << "Failed to get department of package:" << QString::fromStdString(department_key); |
242 | + } |
243 | + } |
244 | + else |
245 | + { |
246 | + app.real_department = app.default_department; |
247 | + if (app.real_department.empty()) |
248 | + { |
249 | + qWarning() << "No default department set in the .desktop file and no entry in the database for" << QString::fromStdString(department_key); |
250 | + } |
251 | + } |
252 | + } |
253 | + |
254 | if (search_query.empty()) { |
255 | result.push_back(app); |
256 | } else { |
257 | |
258 | === modified file 'libclickscope/tests/test_departments-db.cpp' |
259 | --- libclickscope/tests/test_departments-db.cpp 2014-08-05 14:16:26 +0000 |
260 | +++ libclickscope/tests/test_departments-db.cpp 2014-08-12 10:55:35 +0000 |
261 | @@ -53,10 +53,13 @@ |
262 | EXPECT_FALSE(insert_dept_name_query_->isActive()); |
263 | EXPECT_FALSE(select_pkgs_by_dept_->isActive()); |
264 | EXPECT_FALSE(select_pkgs_by_dept_recursive_->isActive()); |
265 | + EXPECT_FALSE(select_dept_for_pkg_->isActive()); |
266 | + EXPECT_FALSE(select_pkgs_count_in_dept_recursive_->isActive()); |
267 | EXPECT_FALSE(select_pkg_by_pkgid_->isActive()); |
268 | EXPECT_FALSE(select_parent_dept_->isActive()); |
269 | EXPECT_FALSE(select_children_depts_->isActive()); |
270 | EXPECT_FALSE(select_dept_name_->isActive()); |
271 | + EXPECT_FALSE(select_is_descendant_of_dept_->isActive()); |
272 | } |
273 | }; |
274 | |
275 | @@ -112,6 +115,35 @@ |
276 | } |
277 | } |
278 | |
279 | +TEST_F(DepartmentsDbTest, testDepartmentForPackageLookup) |
280 | +{ |
281 | + EXPECT_EQ("rpg", db->get_department_for_package("game1")); |
282 | + EXPECT_EQ("fps", db->get_department_for_package("game2")); |
283 | + EXPECT_EQ("office", db->get_department_for_package("app2")); |
284 | + EXPECT_EQ("tools", db->get_department_for_package("app1")); |
285 | + EXPECT_THROW(db->get_department_for_package("foobar"), std::logic_error); |
286 | +} |
287 | + |
288 | +TEST_F(DepartmentsDbTest, testIsDepartmentEmpty) |
289 | +{ |
290 | + EXPECT_TRUE(db->is_empty("card")); |
291 | + EXPECT_FALSE(db->is_empty("")); |
292 | + EXPECT_FALSE(db->is_empty("games")); |
293 | + EXPECT_FALSE(db->is_empty("office")); |
294 | + EXPECT_FALSE(db->is_empty("tools")); |
295 | +} |
296 | + |
297 | +TEST_F(DepartmentsDbTest, testIsDescendantOfDepartment) |
298 | +{ |
299 | + EXPECT_TRUE(db->is_descendant_of_department("rpg", "games")); |
300 | + EXPECT_TRUE(db->is_descendant_of_department("office", "tools")); |
301 | + EXPECT_TRUE(db->is_descendant_of_department("office", "")); |
302 | + EXPECT_TRUE(db->is_descendant_of_department("rpg", "")); |
303 | + EXPECT_TRUE(db->is_descendant_of_department("games", "")); |
304 | + EXPECT_FALSE(db->is_descendant_of_department("games", "office")); |
305 | + EXPECT_FALSE(db->is_descendant_of_department("", "games")); |
306 | +} |
307 | + |
308 | TEST_F(DepartmentsDbTest, testDepartmentNameUpdates) |
309 | { |
310 | { |
311 | @@ -156,10 +188,10 @@ |
312 | } |
313 | { |
314 | auto depts = db->get_children_departments("games"); |
315 | - EXPECT_EQ(3u, depts.size()); |
316 | + EXPECT_EQ(2u, depts.size()); |
317 | EXPECT_TRUE(std::find(depts.begin(), depts.end(), DepartmentsDb::DepartmentInfo("rpg", false)) != depts.end()); |
318 | EXPECT_TRUE(std::find(depts.begin(), depts.end(), DepartmentsDb::DepartmentInfo("fps", false)) != depts.end()); |
319 | - EXPECT_TRUE(std::find(depts.begin(), depts.end(), DepartmentsDb::DepartmentInfo("card", false)) != depts.end()); |
320 | + EXPECT_FALSE(std::find(depts.begin(), depts.end(), DepartmentsDb::DepartmentInfo("card", false)) != depts.end()); |
321 | } |
322 | } |
323 | |
324 | |
325 | === modified file 'scope/clickapps/apps-query.cpp' |
326 | --- scope/clickapps/apps-query.cpp 2014-08-06 17:30:55 +0000 |
327 | +++ scope/clickapps/apps-query.cpp 2014-08-12 10:55:35 +0000 |
328 | @@ -291,11 +291,22 @@ |
329 | searchReply->push(res); |
330 | } |
331 | |
332 | -void click::apps::Query::push_local_departments(scopes::SearchReplyProxy const& replyProxy) |
333 | +void click::apps::Query::push_local_departments(scopes::SearchReplyProxy const& replyProxy, const std::vector<Application>& apps) |
334 | { |
335 | auto const current_dep_id = query().department_id(); |
336 | const std::list<std::string> locales = { search_metadata().locale(), "en_US" }; |
337 | |
338 | + // |
339 | + // create helper lookup of all departments of currently installed apps. |
340 | + // note that apps that are passed here are supposed to be already filterd by current department |
341 | + // that means we only have subdepartments of current department (or subdepartment(s) of subdepartment(s) |
342 | + // and so on of current department, as the hierarchy may be of arbitrary depth. |
343 | + std::unordered_set<std::string> all_subdepartments; |
344 | + for (auto const app: apps) |
345 | + { |
346 | + all_subdepartments.insert(app.real_department); |
347 | + } |
348 | + |
349 | unity::scopes::Department::SPtr root; |
350 | |
351 | try |
352 | @@ -309,17 +320,48 @@ |
353 | // attach subdepartments to it |
354 | for (auto const& subdep: impl->depts_db->get_children_departments(current_dep_id)) |
355 | { |
356 | - // if single supdepartment fails, then ignore it and continue with others |
357 | - try |
358 | - { |
359 | - name = impl->depts_db->get_department_name(subdep.id, locales); |
360 | - unity::scopes::Department::SPtr dep = unity::scopes::Department::create(subdep.id, query(), name); |
361 | - dep->set_has_subdepartments(subdep.has_children); |
362 | - current->add_subdepartment(dep); |
363 | - } |
364 | - catch (const std::exception &e) |
365 | - { |
366 | - qWarning() << "Failed to create subdeparment:" << QString::fromStdString(e.what()); |
367 | + // |
368 | + // check if this subdepartment either directly matches a subdepartment of installed app, |
369 | + // or is any of the departments of installed apps is a descendant of current subdepartment. |
370 | + // the latter means we have app somewhere in the subtree of the current subdepartment, so it |
371 | + // needs to be shown. |
372 | + bool show_subdepartment = false; |
373 | + auto it = all_subdepartments.find(subdep.id); |
374 | + if (it != all_subdepartments.end()) |
375 | + { |
376 | + // subdepartment id matches directly one of the ids from all_subdepartments |
377 | + show_subdepartment = true; |
378 | + all_subdepartments.erase(it); |
379 | + } |
380 | + else |
381 | + { |
382 | + // no direct match - we need to check descendants of this subdepartment |
383 | + // by querying the db |
384 | + for (auto it = all_subdepartments.begin(); it != all_subdepartments.end(); it++) |
385 | + { |
386 | + if (impl->depts_db->is_descendant_of_department(*it, subdep.id)) |
387 | + { |
388 | + show_subdepartment = true; |
389 | + all_subdepartments.erase(it); |
390 | + break; |
391 | + } |
392 | + } |
393 | + } |
394 | + |
395 | + if (show_subdepartment) |
396 | + { |
397 | + // if single supdepartment fails, then ignore it and continue with others |
398 | + try |
399 | + { |
400 | + name = impl->depts_db->get_department_name(subdep.id, locales); |
401 | + unity::scopes::Department::SPtr dep = unity::scopes::Department::create(subdep.id, query(), name); |
402 | + dep->set_has_subdepartments(subdep.has_children); |
403 | + current->add_subdepartment(dep); |
404 | + } |
405 | + catch (const std::exception &e) |
406 | + { |
407 | + qWarning() << "Failed to create subdeparment:" << QString::fromStdString(e.what()); |
408 | + } |
409 | } |
410 | } |
411 | |
412 | @@ -357,7 +399,7 @@ |
413 | if (querystr.empty()) { |
414 | if (impl->depts_db) |
415 | { |
416 | - push_local_departments(searchReply); |
417 | + push_local_departments(searchReply, localResults); |
418 | } |
419 | } |
420 | |
421 | |
422 | === modified file 'scope/clickapps/apps-query.h' |
423 | --- scope/clickapps/apps-query.h 2014-07-22 13:17:28 +0000 |
424 | +++ scope/clickapps/apps-query.h 2014-08-12 10:55:35 +0000 |
425 | @@ -74,7 +74,7 @@ |
426 | |
427 | virtual void add_fake_store_app(scopes::SearchReplyProxy const &replyProxy); |
428 | |
429 | - virtual void push_local_departments(scopes::SearchReplyProxy const& replyProxy); |
430 | + virtual void push_local_departments(scopes::SearchReplyProxy const& replyProxy, const std::vector<Application>& apps); |
431 | |
432 | protected: |
433 | virtual click::Interface& clickInterfaceInstance(); |
434 | |
435 | === modified file 'scope/tests/test_apps_query.cpp' |
436 | --- scope/tests/test_apps_query.cpp 2014-08-05 14:16:26 +0000 |
437 | +++ scope/tests/test_apps_query.cpp 2014-08-12 10:55:35 +0000 |
438 | @@ -192,7 +192,10 @@ |
439 | |
440 | class DepartmentsTest : public ::testing::Test { |
441 | protected: |
442 | - const std::vector<click::Application> installed_apps = {{"app1", "App1", 0.0f, "icon", "url", "descr", "scrshot", ""}}; |
443 | + const std::vector<click::Application> installed_apps = { |
444 | + {"app1", "App1", 0.0f, "icon", "url", "descr", "scrshot", "", "games-rpg"}, |
445 | + {"app2", "App2", 0.0f, "icon", "url", "descr", "scrshot", "", "video"} |
446 | + }; |
447 | const scopes::SearchMetadata metadata{"en_EN", "phone"}; |
448 | const scopes::CategoryRenderer renderer{"{}"}; |
449 | const std::list<std::string> expected_locales {"en_EN", "en_US"}; |
450 | @@ -214,6 +217,7 @@ |
451 | scopes::testing::MockSearchReply mock_reply; |
452 | scopes::SearchReplyProxy reply(&mock_reply, [](unity::scopes::SearchReply*){}); |
453 | |
454 | + // no apps in 'books' department, thus excluded |
455 | std::list<std::string> expected_departments({{"", "games", "video"}}); |
456 | |
457 | EXPECT_CALL(*clickif, find_installed_apps(_, _, _)).WillOnce(Return(installed_apps)); |
458 | @@ -222,14 +226,25 @@ |
459 | EXPECT_CALL(mock_reply, register_category("store", _, _, _)).WillOnce(Return(ptrCat)); |
460 | EXPECT_CALL(mock_reply, register_departments(MatchesDepartments(expected_departments))); |
461 | |
462 | - EXPECT_CALL(mock_reply, push(Matcher<unity::scopes::CategorisedResult const&>(_))).Times(2).WillRepeatedly(Return(true)); |
463 | + EXPECT_CALL(mock_reply, push(Matcher<unity::scopes::CategorisedResult const&>(_))).Times(3).WillRepeatedly(Return(true)); |
464 | + |
465 | + ON_CALL(*depts_db, is_descendant_of_department(_, _)).WillByDefault(Return(false)); |
466 | + ON_CALL(*depts_db, is_descendant_of_department("games", "")).WillByDefault(Return(true)); |
467 | + ON_CALL(*depts_db, is_descendant_of_department("games-rpg", "games")).WillByDefault(Return(true)); |
468 | + ON_CALL(*depts_db, is_descendant_of_department("books", "")).WillByDefault(Return(true)); |
469 | + ON_CALL(*depts_db, is_descendant_of_department("video", "")).WillByDefault(Return(true)); |
470 | |
471 | EXPECT_CALL(*depts_db, get_department_name("games", expected_locales)).WillOnce(Return("Games")); |
472 | EXPECT_CALL(*depts_db, get_department_name("video", expected_locales)).WillOnce(Return("Video")); |
473 | + EXPECT_CALL(*depts_db, is_empty("games")).WillRepeatedly(Return(false)); |
474 | + EXPECT_CALL(*depts_db, is_empty("video")).WillRepeatedly(Return(false)); |
475 | + EXPECT_CALL(*depts_db, is_empty("books")).WillRepeatedly(Return(false)); |
476 | + EXPECT_CALL(*depts_db, is_descendant_of_department(_, _)).Times(AnyNumber()); |
477 | EXPECT_CALL(*depts_db, get_children_departments("")).WillOnce(Return( |
478 | std::list<click::DepartmentsDb::DepartmentInfo>({ |
479 | - {"games", false}, |
480 | - {"video", true} |
481 | + {"games", true}, |
482 | + {"video", true}, |
483 | + {"books", true} |
484 | })) |
485 | ); |
486 | |
487 | @@ -259,7 +274,7 @@ |
488 | EXPECT_CALL(mock_reply, register_category("store", _, _, _)).WillOnce(Return(ptrCat)); |
489 | EXPECT_CALL(mock_reply, register_departments(MatchesDepartments(expected_departments))); |
490 | |
491 | - EXPECT_CALL(mock_reply, push(Matcher<unity::scopes::CategorisedResult const&>(_))).Times(2).WillRepeatedly(Return(true)); |
492 | + EXPECT_CALL(mock_reply, push(Matcher<unity::scopes::CategorisedResult const&>(_))).Times(3).WillRepeatedly(Return(true)); |
493 | |
494 | EXPECT_CALL(*depts_db, get_parent_department_id("games")).WillOnce(Return("")); |
495 | EXPECT_CALL(*depts_db, get_department_name("games", expected_locales)).WillOnce(Return("Games")); |
496 | @@ -290,7 +305,7 @@ |
497 | EXPECT_CALL(mock_reply, register_category("local", StrEq(""), _, _)).WillOnce(Return(ptrCat)); |
498 | EXPECT_CALL(mock_reply, register_category("store", _, _, _)).WillOnce(Return(ptrCat)); |
499 | |
500 | - EXPECT_CALL(mock_reply, push(Matcher<unity::scopes::CategorisedResult const&>(_))).Times(2).WillRepeatedly(Return(true)); |
501 | + EXPECT_CALL(mock_reply, push(Matcher<unity::scopes::CategorisedResult const&>(_))).Times(3).WillRepeatedly(Return(true)); |
502 | |
503 | q.run(reply); |
504 | } |
505 | |
506 | === modified file 'scope/tests/test_helpers.h' |
507 | --- scope/tests/test_helpers.h 2014-07-18 15:01:41 +0000 |
508 | +++ scope/tests/test_helpers.h 2014-08-12 10:55:35 +0000 |
509 | @@ -65,6 +65,8 @@ |
510 | MOCK_METHOD2(get_packages_for_department, std::unordered_set<std::string>(const std::string&, bool)); |
511 | MOCK_METHOD1(get_parent_department_id, std::string(const std::string&)); |
512 | MOCK_METHOD1(get_children_departments, std::list<click::DepartmentsDb::DepartmentInfo>(const std::string&)); |
513 | + MOCK_METHOD1(is_empty, bool(const std::string&)); |
514 | + MOCK_METHOD2(is_descendant_of_department, bool(const std::string&, const std::string&)); |
515 | |
516 | MOCK_METHOD2(store_package_mapping, void(const std::string&, const std::string&)); |
517 | MOCK_METHOD2(store_department_mapping, void(const std::string&, const std::string&)); |
PASSED: Continuous integration, rev:397 jenkins. qa.ubuntu. com/job/ unity-team- unity-scope- click-devel- ci/255/ jenkins. qa.ubuntu. com/job/ unity-team- unity-scope- click-devel- utopic- amd64-ci/ 230 jenkins. qa.ubuntu. com/job/ unity-team- unity-scope- click-devel- utopic- armhf-ci/ 229 jenkins. qa.ubuntu. com/job/ unity-team- unity-scope- click-devel- utopic- armhf-ci/ 229/artifact/ work/output/ *zip*/output. zip jenkins. qa.ubuntu. com/job/ unity-team- unity-scope- click-devel- utopic- i386-ci/ 229
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/unity- team-unity- scope-click- devel-ci/ 255/rebuild
http://