Merge lp:~rmescandon/scopecreator/rss-template-read-settings-from-metadata into lp:~scopecreator-team/scopecreator/rss-template

Proposed by Roberto Mier Escandon
Status: Merged
Merged at revision: 11
Proposed branch: lp:~rmescandon/scopecreator/rss-template-read-settings-from-metadata
Merge into: lp:~scopecreator-team/scopecreator/rss-template
Prerequisite: lp:~rmescandon/scopecreator/rss-template-keywords-support
Diff against target: 423 lines (+180/-84)
6 files modified
data/rss.canonical_rss.ini.in (+3/-0)
include/scope/query.h (+13/-2)
include/scope/scope.h (+3/-0)
po/rss.pot (+6/-2)
src/scope/query.cpp (+147/-75)
src/scope/scope.cpp (+8/-5)
To merge this branch: bzr merge lp:~rmescandon/scopecreator/rss-template-read-settings-from-metadata
Reviewer Review Type Date Requested Status
Scopecreator Team Pending
Review via email: mp+266816@code.launchpad.net

Commit message

- removed not needed boost foreach. Used usual for
- avoid including empty categories (no title or url)
- included scope metadata in query search
- readed logo, emblem, date time format from scope metadata instead of hardcoded path
- included BigFirstResult boolean setting in .ini file appearance section to show or not with a big image the first received result in surface mode, if not aggregated

NOTE:These features are only working on Desktop. In case Ubuntu Touch, I cannot get registry()->get_metadata() for any scope id. Scope has a weird behave. It gets stopped when tried to execute that instruction (same happens if I try registry()->list, but i can get the registry id or url)

Description of the change

- removed not needed boost foreach. Used usual for
- avoid including empty categories (no title or url)
- included scope metadata in query search
- readed logo, emblem, date time format from scope metadata instead of hardcoded path
- included BigFirstResult boolean setting in .ini file appearance section to show or not with a big image the first received result in surface mode, if not aggregated

NOTE:These features are only working on Desktop. In case Ubuntu Touch, I cannot get registry()->get_metadata() for any scope id. Scope has a weird behave. It gets stopped when tried to execute that instruction (same happens if I try registry()->list, but i can get the registry id or url)

To post a comment you must log in.
18. By Roberto Mier Escandon

fixed problem with metadata. MUST BE FIXED:only working on desktop, on armhf is giving 'aa_getcon failed, errno = 13
' error

19. By Roberto Mier Escandon

fixed problem with date format transform. Updated first big result setting management

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'data/rss.canonical_rss.ini.in'
2--- data/rss.canonical_rss.ini.in 2015-08-08 13:36:27 +0000
3+++ data/rss.canonical_rss.ini.in 2015-08-08 13:36:27 +0000
4@@ -10,3 +10,6 @@
5 PageHeader.Logo=logo.png
6 PageHeader.Background=color:///#e9e7e8
7 PageHeader.DividerColor=#ffeb00
8+Emblem=logo.png
9+DateTimeFormat=hh:mm, d MMMM
10+BigFirstResult=true
11
12=== modified file 'include/scope/query.h'
13--- include/scope/query.h 2015-08-08 13:36:27 +0000
14+++ include/scope/query.h 2015-08-08 13:36:27 +0000
15@@ -40,7 +40,7 @@
16 public:
17 Query(const unity::scopes::CannedQuery &query,
18 const unity::scopes::SearchMetadata &metadata,
19- const std::string scope_directory);
20+ const unity::scopes::ScopeMetadata &scope_metadata);
21
22 ~Query() = default;
23
24@@ -50,7 +50,7 @@
25
26 private:
27 api::Client client_;
28- std::string scope_directory_;
29+ unity::scopes::ScopeMetadata scope_metadata_;
30
31 /// @brief keyword_feeds_ map correlating aggregator scopes keywords to feed urls
32 std::map<std::string, std::string> keyword_feeds_;
33@@ -65,6 +65,17 @@
34 /// from an aggregator scope. If found, it is returned a std::pair with the feed url (pair.second) and its related
35 /// search keyword (pair.first)
36 std::pair<std::string, std::string> find_url_for_keywords(const std::set<std::string>& search_keywords);
37+
38+ /// @brief get_emblem gets the emblem by reading the appearance parameter "Emblem" value if set. If not set,
39+ /// scope_directory/emblem.png file is used by default
40+ std::string get_emblem();
41+
42+ /// @brief get_date_time_format returns the format to be shown for the date and time for every result shown in an
43+ /// aggregator scope. If this parameter is not set, the default format is 'hh:mm, d MMMM'
44+ std::string get_date_time_format();
45+
46+ /// @brief get_big_first_result returns true if wanted to have first returned value in a format with a big image and overlayed
47+ bool get_big_first_result();
48 };
49
50 }
51
52=== modified file 'include/scope/scope.h'
53--- include/scope/scope.h 2015-03-25 03:17:53 +0000
54+++ include/scope/scope.h 2015-08-08 13:36:27 +0000
55@@ -62,6 +62,9 @@
56 unity::scopes::SearchQueryBase::UPtr search(
57 unity::scopes::CannedQuery const& q,
58 unity::scopes::SearchMetadata const&) override;
59+
60+private:
61+ std::string scope_id_;
62 };
63
64 }
65
66=== modified file 'po/rss.pot'
67--- po/rss.pot 2015-08-08 13:36:27 +0000
68+++ po/rss.pot 2015-08-08 13:36:27 +0000
69@@ -8,7 +8,7 @@
70 msgstr ""
71 "Project-Id-Version: PACKAGE VERSION\n"
72 "Report-Msgid-Bugs-To: \n"
73-"POT-Creation-Date: 2015-08-03 17:04+0200\n"
74+"POT-Creation-Date: 2015-08-08 15:34+0200\n"
75 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
76 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
77 "Language-Team: LANGUAGE <LL@li.org>\n"
78@@ -21,6 +21,10 @@
79 msgid "Vox"
80 msgstr ""
81
82-#: ../src/scope/query.cpp:266
83+#: ../src/scope/query.cpp:297
84 msgid "Open"
85 msgstr ""
86+
87+#: ../src/scope/query.cpp:304
88+msgid "More from "
89+msgstr ""
90
91=== modified file 'src/scope/query.cpp'
92--- src/scope/query.cpp 2015-08-08 13:36:27 +0000
93+++ src/scope/query.cpp 2015-08-08 13:36:27 +0000
94@@ -19,7 +19,6 @@
95
96 #include <boost/algorithm/string/trim.hpp>
97 #include <boost/algorithm/string/predicate.hpp>
98-#include <boost/foreach.hpp>
99
100 #include <scope/localization.h>
101 #include <scope/query.h>
102@@ -29,6 +28,7 @@
103 #include <unity/scopes/CategoryRenderer.h>
104 #include <unity/scopes/Department.h>
105 #include <unity/scopes/QueryBase.h>
106+#include <unity/scopes/CannedQuery.h>
107 #include <unity/scopes/SearchReply.h>
108 #include <unity/scopes/VariantBuilder.h>
109 #include <unity/scopes/SearchMetadata.h>
110@@ -43,8 +43,6 @@
111 #include <QJsonObject>
112 #include <QDateTime>
113
114-#define foreach BOOST_FOREACH
115-
116 namespace sc = unity::scopes;
117 namespace alg = boost::algorithm;
118
119@@ -52,6 +50,23 @@
120 using namespace api;
121 using namespace scope;
122
123+std::string FIRST_NEWS_LAYOUT = R"(
124+{
125+ "schema-version" : 1,
126+ "template" : {
127+ "category-layout" : "grid",
128+ "card-size": "large",
129+ "overlay": true
130+ },
131+ "components" : {
132+ "title" : "title",
133+ "art" : {
134+ "field": "art",
135+ "aspect-ratio": 2.1
136+ }
137+ }
138+}
139+)";
140
141 std::string NEWS_LAYOUT = R"(
142 {
143@@ -147,29 +162,28 @@
144 }
145
146 pair<string,string> Query::find_url_for_keywords(const set<string>& search_keywords) {
147- foreach(string search_keyword, search_keywords) {
148+ for(const string& search_keyword : search_keywords) {
149 auto it = keyword_feeds_.find(search_keyword);
150 if (it != keyword_feeds_.end()) {
151- string found_url = it->second;
152+ const string& found_url = it->second;
153 return std::pair<string, string>(search_keyword, found_url);
154 }
155 }
156 return std::pair<string, string>{};
157 }
158
159-Query::Query(const sc::CannedQuery &query, const sc::SearchMetadata &metadata, const string scope_directory) :
160- sc::SearchQueryBase(query, metadata),
161- client_(),
162- scope_directory_(scope_directory) {
163+Query::Query(const sc::CannedQuery &query, const sc::SearchMetadata &search_metadata, const sc::ScopeMetadata& scope_metadata) :
164+ sc::SearchQueryBase(query, search_metadata),
165+ client_{},
166+ scope_metadata_{scope_metadata} {
167 }
168
169 void Query::cancelled() {
170 client_.cancel();
171 }
172
173-
174 void Query::run(sc::SearchReplyProxy const& reply) {
175- try {
176+ try {
177 // Start by getting information about the query
178 const sc::CannedQuery &query(sc::SearchQueryBase::query());
179
180@@ -177,7 +191,7 @@
181 string query_string = alg::trim_copy(query.query_string());
182
183 // Get the departments
184- QString deptFile = QString::fromStdString(scope_directory_) + "/feeds.json";
185+ QString deptFile = QString::fromStdString(scope_metadata_.scope_directory()) + "/feeds.json";
186 string feedUrl = getDepartments(deptFile, reply).toStdString(); // feedUrl has the root URL
187
188 // Check if the search comes from an aggregator scope
189@@ -203,74 +217,105 @@
190
191 vector<Client::Item> results = client_.getItems(feedUrl);
192
193- // Register a category for the forecast
194+ // Register a category for the common news
195 auto news_cat = reply->register_category("news",
196 "", "", sc::CategoryRenderer(NEWS_LAYOUT));
197-
198- // For each of the forecast days
199- for (const auto &item : results) {
200-
201- // Filter by search term if we have one
202- if (!query_string.empty()) {
203- QString qry = QString::fromStdString(query_string);
204- QString title = QString::fromStdString(item.title);
205- QString summary = QString::fromStdString(item.summary);
206- QString content = QString::fromStdString(item.content);
207-
208- if (!title.contains(qry, Qt::CaseInsensitive) &&
209- !summary.contains(qry, Qt::CaseInsensitive) &&
210- !content.contains(qry, Qt::CaseInsensitive)) {
211- continue;
212+ auto first_news_cat = reply->register_category("first_news",
213+ "", "", sc::CategoryRenderer(FIRST_NEWS_LAYOUT));
214+
215+ if (results.size() > 0) {
216+
217+ // Get common values for all results to avoid asking for them in every iteration
218+ std::string emblem = get_emblem();
219+ std::string date_time_format = get_date_time_format();
220+ bool show_big_result = get_big_first_result();
221+
222+ // For each of the results vector items
223+ for (const auto &item : results) {
224+
225+ // Filter by search term if we have one
226+ if (!query_string.empty()) {
227+ QString qry = QString::fromStdString(query_string);
228+ QString title = QString::fromStdString(item.title);
229+ QString summary = QString::fromStdString(item.summary);
230+ QString content = QString::fromStdString(item.content);
231+
232+ if (!title.contains(qry, Qt::CaseInsensitive) &&
233+ !summary.contains(qry, Qt::CaseInsensitive) &&
234+ !content.contains(qry, Qt::CaseInsensitive)) {
235+ continue;
236+ }
237 }
238- }
239-
240- // Create a result
241- sc::CategorisedResult res(news_cat);
242-
243- // We must have a URI
244- res.set_uri(item.uri);
245- res.set_dnd_uri(item.uri);
246-
247- // Set the rest of the attributes
248- res.set_title(item.title);
249- res.set_art(item.art);
250- res["published"] = sc::Variant(item.published);
251- res["author"] = sc::Variant(item.author);
252- res["summary"] = sc::Variant(item.summary);
253- res["content"] = sc::Variant(item.content);
254- res["emblem"] = sc::Variant(scope_directory_+"/images/emblem.png");
255-
256- if (res.art().empty()) {
257- res.set_art(scope_directory_ + "/icon.png");
258- }
259-
260- // if searched from aggregated, set formatted date to subtitle in case found keyword is related with news
261- if (meta.is_aggregated()) {
262- if (boost::starts_with(found_keyword, "news.")) {
263+
264+ // Create a result if having title at least
265+ if (!item.title.empty() && !item.uri.empty()) {
266+
267+ // If surfacing in not aggregated mode and set big-first-result setting to true, show first result in big
268+ sc::Category::SCPtr cat =
269+ show_big_result && !meta.is_aggregated() && query_string.empty() ?
270+ first_news_cat :
271+ news_cat;
272+
273+ show_big_result = false;
274+
275+ sc::CategorisedResult res(cat);
276+
277+ // We must have a URI
278+ res.set_uri(item.uri);
279+ res.set_dnd_uri(item.uri);
280+
281+ // Set the rest of the attributes
282+ res.set_title(item.title);
283+ res.set_art(item.art);
284+ res["author"] = sc::Variant(item.author);
285+ res["summary"] = sc::Variant(item.summary);
286+ res["content"] = sc::Variant(item.content);
287+ res["emblem"] = sc::Variant(emblem);
288+
289+ if (res.art().empty()) {
290+ res.set_art(scope_metadata_.icon());
291+ }
292+
293 QString date = QString::fromStdString(item.published);
294+
295 if (!date.isEmpty()){
296- QDateTime ipostTime = QDateTime::fromString(date, Qt::RFC2822Date);
297- QString readeableTime = ipostTime.toString("hh:mm, d MMMM");
298- res["subtitle"] = readeableTime.toStdString();
299- }
300- }
301- }
302-
303- sc::VariantBuilder actions;
304- actions.add_tuple({
305- {"id", sc::Variant("open")},
306- {"label", sc::Variant(_("Open"))},
307- {"uri", sc::Variant(res.dnd_uri())}
308- });
309- res["actions"] = actions.end();
310-
311- // Push the result
312- if (!reply->push(res)) {
313- // If we fail to push, it means the query has been cancelled.
314- // So don't continue;
315- return;
316- }
317- }
318+ QDateTime ipostTime = QDateTime::fromString(date, Qt::ISODate);
319+ QString readableTime = ipostTime.toString(QString::fromStdString(date_time_format));
320+ res["published"] = readableTime.toStdString();
321+ }
322+
323+ // if searched from aggregated, set formatted date to subtitle in case found keyword is related with news
324+ if (meta.is_aggregated()) {
325+ if (boost::starts_with(found_keyword, "news.")) {
326+ res["subtitle"] = res["published"];
327+ }
328+ }
329+
330+ sc::VariantBuilder actions;
331+ actions.add_tuple({
332+ {"id", sc::Variant("open")},
333+ {"label", sc::Variant(_("Open"))},
334+ {"uri", sc::Variant(res.dnd_uri())}
335+ });
336+
337+ if (meta.is_aggregated()) {
338+ actions.add_tuple({
339+ {"id", sc::Variant("more")},
340+ {"label", sc::Variant(_("More from ") + scope_metadata_.display_name())},
341+ {"uri", sc::Variant(query.to_uri())}
342+ });
343+ }
344+ res["actions"] = actions.end();
345+
346+ // Push the result
347+ if (!reply->push(res)) {
348+ // If we fail to push, it means the query has been cancelled.
349+ // So don't continue;
350+ return;
351+ }
352+ } // end if (!item.title.empty() && !item.uri.empty()) ...
353+ } // end for (const auto &item : results) ...
354+ } // end if (results.size > 0) ...
355
356 } catch (domain_error &e) {
357 // Handle exceptions being thrown by the client API
358@@ -279,3 +324,30 @@
359 }
360 }
361
362+string Query::get_emblem() {
363+ const auto& map = scope_metadata_.appearance_attributes();
364+ auto it = map.find("emblem");
365+ if (it != map.end()) {
366+ return scope_metadata_.scope_directory() + "/" + it->second.get_string();
367+ }
368+ return scope_metadata_.scope_directory() + "/emblem.png";
369+}
370+
371+string Query::get_date_time_format() {
372+ const auto& map = scope_metadata_.appearance_attributes();
373+ auto it = map.find("date-time-format");
374+ if (it != map.end()) {
375+ return it->second.get_string();
376+ }
377+ return "hh:mm, d MMMM";
378+}
379+
380+bool Query::get_big_first_result() {
381+ const auto& map = scope_metadata_.appearance_attributes();
382+ auto it = map.find("big-first-result");
383+ if (it != map.end()) {
384+ return it->second.get_bool();
385+ }
386+ return false;
387+}
388+
389
390=== modified file 'src/scope/scope.cpp'
391--- src/scope/scope.cpp 2015-03-25 03:17:53 +0000
392+++ src/scope/scope.cpp 2015-08-08 13:36:27 +0000
393@@ -1,4 +1,4 @@
394-/*
395+/*
396 * Copyright 2015 Canonical Ltd.
397 *
398 * This program is free software; you can redistribute it and/or modify
399@@ -31,7 +31,9 @@
400 using namespace api;
401 using namespace scope;
402
403-void Scope::start(string const&) {
404+void Scope::start(string const& scope_id) {
405+
406+ scope_id_ = scope_id;
407
408 setlocale(LC_ALL, "");
409 string translation_directory = ScopeBase::scope_directory()
410@@ -43,9 +45,10 @@
411 }
412
413 sc::SearchQueryBase::UPtr Scope::search(const sc::CannedQuery &query,
414- const sc::SearchMetadata &metadata) {
415- // Boilerplate construction of Query
416- return sc::SearchQueryBase::UPtr(new Query(query, metadata, scope_directory()));
417+ const sc::SearchMetadata &search_metadata) {
418+ // Include scope metadata into the query object
419+ const sc::ScopeMetadata& scope_metadata = registry()->get_metadata(scope_id_);
420+ return sc::SearchQueryBase::UPtr(new Query(query, search_metadata, scope_metadata));
421 }
422
423 sc::PreviewQueryBase::UPtr Scope::preview(sc::Result const& result,

Subscribers

People subscribed via source and target branches