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

Proposed by Roberto Mier Escandón  on 2015-08-08
Status: Merged
Merged at revision: 11
Proposed branch: lp:~rmescandon/scopecreator/rss-template-read-settings-from-metadata-take2
Merge into: lp:~scopecreator-team/scopecreator/rss-template
Prerequisite: lp:~rmescandon/scopecreator/rss-template-keywords-support
Diff against target: 455 lines (+203/-82)
6 files modified
data/rss.canonical_rss.ini.in (+3/-0)
include/scope/query.h (+23/-1)
include/scope/scope.h (+9/-0)
po/rss.pot (+6/-2)
src/scope/query.cpp (+143/-74)
src/scope/scope.cpp (+19/-5)
To merge this branch: bzr merge lp:~rmescandon/scopecreator/rss-template-read-settings-from-metadata-take2
Reviewer Review Type Date Requested Status
Scott Sweeny (community) 2015-08-08 Approve on 2015-09-04
Review via email: mp+267443@code.launchpad.net

Commit message

Same features than branch
scopecreator/rss-template-read-settings-from-metadata

but reading scope .ini file directly using QSettings instead of using Scope::metadata

This solution is working well and can be used as alternative to scopecreator/rss-template-read-settings-from-metadata branch. Only one of both should be merged

Description of the change

Same features than branch
scopecreator/rss-template-read-settings-from-metadata

but reading scope .ini file directly using QSettings instead of using Scope::metadata

This solution is working well and can be used as alternative to scopecreator/rss-template-read-settings-from-metadata branch. Only one of both should be merged

To post a comment you must log in.
Scott Sweeny (ssweeny) wrote :

I've been running a scope based on this for a few weeks now and it works flawlessly :-)

Merging.

review: Approve

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

Subscribers

People subscribed via source and target branches