Merge lp:~rmescandon/scopecreator/rss-template-read-settings-from-metadata-take2 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-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) Approve
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.
Revision history for this message
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
=== modified file 'data/rss.canonical_rss.ini.in'
--- data/rss.canonical_rss.ini.in 2015-08-08 22:18:29 +0000
+++ data/rss.canonical_rss.ini.in 2015-08-08 22:18:29 +0000
@@ -10,3 +10,6 @@
10PageHeader.Logo=logo.png10PageHeader.Logo=logo.png
11PageHeader.Background=color:///#e9e7e811PageHeader.Background=color:///#e9e7e8
12PageHeader.DividerColor=#ffeb0012PageHeader.DividerColor=#ffeb00
13Emblem=logo.png
14DateTimeFormat="hh:mm, d MMMM"
15BigFirstResult=true
1316
=== modified file 'include/scope/query.h'
--- include/scope/query.h 2015-08-08 22:18:29 +0000
+++ include/scope/query.h 2015-08-08 22:18:29 +0000
@@ -25,6 +25,9 @@
25#include <unity/scopes/SearchQueryBase.h>25#include <unity/scopes/SearchQueryBase.h>
26#include <unity/scopes/ReplyProxyFwd.h>26#include <unity/scopes/ReplyProxyFwd.h>
2727
28#include <QSharedPointer>
29#include <QSettings>
30
28#include <map>31#include <map>
2932
30namespace scope {33namespace scope {
@@ -40,7 +43,8 @@
40public:43public:
41 Query(const unity::scopes::CannedQuery &query,44 Query(const unity::scopes::CannedQuery &query,
42 const unity::scopes::SearchMetadata &metadata,45 const unity::scopes::SearchMetadata &metadata,
43 const std::string scope_directory);46 const std::string& scope_directory,
47 const QSharedPointer<QSettings>& scopeConfig);
4448
45 ~Query() = default;49 ~Query() = default;
4650
@@ -51,6 +55,7 @@
51private:55private:
52 api::Client client_;56 api::Client client_;
53 std::string scope_directory_;57 std::string scope_directory_;
58 QSharedPointer<QSettings> mScopeConfig;
5459
55 /// @brief keyword_feeds_ map correlating aggregator scopes keywords to feed urls60 /// @brief keyword_feeds_ map correlating aggregator scopes keywords to feed urls
56 std::map<std::string, std::string> keyword_feeds_;61 std::map<std::string, std::string> keyword_feeds_;
@@ -65,6 +70,23 @@
65 /// from an aggregator scope. If found, it is returned a std::pair with the feed url (pair.second) and its related70 /// from an aggregator scope. If found, it is returned a std::pair with the feed url (pair.second) and its related
66 /// search keyword (pair.first)71 /// search keyword (pair.first)
67 std::pair<std::string, std::string> find_url_for_keywords(const std::set<std::string>& search_keywords);72 std::pair<std::string, std::string> find_url_for_keywords(const std::set<std::string>& search_keywords);
73
74 /// @brief get_display_name returns the scope name to display
75 std::string get_display_name();
76
77 /// @brief get_icon returns the scoe icon file path. scope_directory/icon.png if value is not set in scope config
78 std::string get_icon();
79
80 /// @brief get_emblem gets the emblem by reading the appearance parameter "Emblem" value if set. If not set,
81 /// scope_directory/emblem.png file is used by default
82 std::string get_emblem();
83
84 /// @brief get_date_time_format returns the format to be shown for the date and time for every result shown in an
85 /// aggregator scope. If this parameter is not set, the default format is 'hh:mm, d MMMM'
86 std::string get_date_time_format();
87
88 /// @brief get_big_first_result returns true if wanted to have first returned value in a format with a big image and overlayed
89 bool get_big_first_result();
68};90};
6991
70}92}
7193
=== modified file 'include/scope/scope.h'
--- include/scope/scope.h 2015-03-25 03:17:53 +0000
+++ include/scope/scope.h 2015-08-08 22:18:29 +0000
@@ -28,6 +28,9 @@
28#include <unity/scopes/QueryBase.h>28#include <unity/scopes/QueryBase.h>
29#include <unity/scopes/PreviewQueryBase.h>29#include <unity/scopes/PreviewQueryBase.h>
3030
31#include <QSettings>
32#include <QSharedPointer>
33
31namespace scope {34namespace scope {
3235
33/**36/**
@@ -62,6 +65,12 @@
62 unity::scopes::SearchQueryBase::UPtr search(65 unity::scopes::SearchQueryBase::UPtr search(
63 unity::scopes::CannedQuery const& q,66 unity::scopes::CannedQuery const& q,
64 unity::scopes::SearchMetadata const&) override;67 unity::scopes::SearchMetadata const&) override;
68
69private:
70 std::string scope_id_;
71 QSharedPointer<QSettings> mScopeConfig;
72
73 void loadScopeConfig();
65};74};
6675
67}76}
6877
=== modified file 'po/rss.pot'
--- po/rss.pot 2015-08-08 22:18:29 +0000
+++ po/rss.pot 2015-08-08 22:18:29 +0000
@@ -8,7 +8,7 @@
8msgstr ""8msgstr ""
9"Project-Id-Version: PACKAGE VERSION\n"9"Project-Id-Version: PACKAGE VERSION\n"
10"Report-Msgid-Bugs-To: \n"10"Report-Msgid-Bugs-To: \n"
11"POT-Creation-Date: 2015-08-03 17:04+0200\n"11"POT-Creation-Date: 2015-08-09 00:05+0200\n"
12"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"12"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
13"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"13"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
14"Language-Team: LANGUAGE <LL@li.org>\n"14"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -21,6 +21,10 @@
21msgid "Vox"21msgid "Vox"
22msgstr ""22msgstr ""
2323
24#: ../src/scope/query.cpp:26624#: ../src/scope/query.cpp:309
25msgid "Open"25msgid "Open"
26msgstr ""26msgstr ""
27
28#: ../src/scope/query.cpp:316
29msgid "More from "
30msgstr ""
2731
=== modified file 'src/scope/query.cpp'
--- src/scope/query.cpp 2015-08-08 22:18:29 +0000
+++ src/scope/query.cpp 2015-08-08 22:18:29 +0000
@@ -19,7 +19,6 @@
1919
20#include <boost/algorithm/string/trim.hpp>20#include <boost/algorithm/string/trim.hpp>
21#include <boost/algorithm/string/predicate.hpp>21#include <boost/algorithm/string/predicate.hpp>
22#include <boost/foreach.hpp>
2322
24#include <scope/localization.h>23#include <scope/localization.h>
25#include <scope/query.h>24#include <scope/query.h>
@@ -29,6 +28,7 @@
29#include <unity/scopes/CategoryRenderer.h>28#include <unity/scopes/CategoryRenderer.h>
30#include <unity/scopes/Department.h>29#include <unity/scopes/Department.h>
31#include <unity/scopes/QueryBase.h>30#include <unity/scopes/QueryBase.h>
31#include <unity/scopes/CannedQuery.h>
32#include <unity/scopes/SearchReply.h>32#include <unity/scopes/SearchReply.h>
33#include <unity/scopes/VariantBuilder.h>33#include <unity/scopes/VariantBuilder.h>
34#include <unity/scopes/SearchMetadata.h>34#include <unity/scopes/SearchMetadata.h>
@@ -43,8 +43,6 @@
43#include <QJsonObject>43#include <QJsonObject>
44#include <QDateTime>44#include <QDateTime>
4545
46#define foreach BOOST_FOREACH
47
48namespace sc = unity::scopes;46namespace sc = unity::scopes;
49namespace alg = boost::algorithm;47namespace alg = boost::algorithm;
5048
@@ -52,6 +50,23 @@
52using namespace api;50using namespace api;
53using namespace scope;51using namespace scope;
5452
53std::string FIRST_NEWS_LAYOUT = R"(
54{
55 "schema-version" : 1,
56 "template" : {
57 "category-layout" : "grid",
58 "card-size": "large",
59 "overlay": true
60 },
61 "components" : {
62 "title" : "title",
63 "art" : {
64 "field": "art",
65 "aspect-ratio": 2.1
66 }
67 }
68}
69)";
5570
56std::string NEWS_LAYOUT = R"(71std::string NEWS_LAYOUT = R"(
57{72{
@@ -147,29 +162,32 @@
147}162}
148163
149pair<string,string> Query::find_url_for_keywords(const set<string>& search_keywords) {164pair<string,string> Query::find_url_for_keywords(const set<string>& search_keywords) {
150 foreach(string search_keyword, search_keywords) {165 for(const string& search_keyword : search_keywords) {
151 auto it = keyword_feeds_.find(search_keyword);166 auto it = keyword_feeds_.find(search_keyword);
152 if (it != keyword_feeds_.end()) {167 if (it != keyword_feeds_.end()) {
153 string found_url = it->second;168 const string& found_url = it->second;
154 return std::pair<string, string>(search_keyword, found_url);169 return std::pair<string, string>(search_keyword, found_url);
155 }170 }
156 }171 }
157 return std::pair<string, string>{};172 return std::pair<string, string>{};
158}173}
159174
160Query::Query(const sc::CannedQuery &query, const sc::SearchMetadata &metadata, const string scope_directory) :175Query::Query(const sc::CannedQuery &query,
161 sc::SearchQueryBase(query, metadata),176 const sc::SearchMetadata &search_metadata,
162 client_(),177 const string& scope_directory,
163 scope_directory_(scope_directory) {178 const QSharedPointer<QSettings>& scopeConfig)
179 : sc::SearchQueryBase(query, search_metadata)
180 , client_{}
181 , scope_directory_{scope_directory}
182 , mScopeConfig{scopeConfig} {
164}183}
165184
166void Query::cancelled() {185void Query::cancelled() {
167 client_.cancel();186 client_.cancel();
168}187}
169188
170
171void Query::run(sc::SearchReplyProxy const& reply) {189void Query::run(sc::SearchReplyProxy const& reply) {
172 try { 190 try {
173 // Start by getting information about the query191 // Start by getting information about the query
174 const sc::CannedQuery &query(sc::SearchQueryBase::query());192 const sc::CannedQuery &query(sc::SearchQueryBase::query());
175193
@@ -203,74 +221,105 @@
203221
204 vector<Client::Item> results = client_.getItems(feedUrl);222 vector<Client::Item> results = client_.getItems(feedUrl);
205223
206 // Register a category for the forecast224 // Register a category for the common news
207 auto news_cat = reply->register_category("news",225 auto news_cat = reply->register_category("news",
208 "", "", sc::CategoryRenderer(NEWS_LAYOUT));226 "", "", sc::CategoryRenderer(NEWS_LAYOUT));
209227 auto first_news_cat = reply->register_category("first_news",
210 // For each of the forecast days228 "", "", sc::CategoryRenderer(FIRST_NEWS_LAYOUT));
211 for (const auto &item : results) {229
212230 if (results.size() > 0) {
213 // Filter by search term if we have one231
214 if (!query_string.empty()) {232 // Get common values for all results to avoid asking for them in every iteration
215 QString qry = QString::fromStdString(query_string);233 std::string emblem = get_emblem();
216 QString title = QString::fromStdString(item.title);234 std::string date_time_format = get_date_time_format();
217 QString summary = QString::fromStdString(item.summary);235 bool show_big_result = get_big_first_result();
218 QString content = QString::fromStdString(item.content);236
219237 // For each of the results vector items
220 if (!title.contains(qry, Qt::CaseInsensitive) &&238 for (const auto &item : results) {
221 !summary.contains(qry, Qt::CaseInsensitive) &&239
222 !content.contains(qry, Qt::CaseInsensitive)) {240 // Filter by search term if we have one
223 continue;241 if (!query_string.empty()) {
242 QString qry = QString::fromStdString(query_string);
243 QString title = QString::fromStdString(item.title);
244 QString summary = QString::fromStdString(item.summary);
245 QString content = QString::fromStdString(item.content);
246
247 if (!title.contains(qry, Qt::CaseInsensitive) &&
248 !summary.contains(qry, Qt::CaseInsensitive) &&
249 !content.contains(qry, Qt::CaseInsensitive)) {
250 continue;
251 }
224 }252 }
225 }253
226254 // Create a result if having title at least
227 // Create a result255 if (!item.title.empty() && !item.uri.empty()) {
228 sc::CategorisedResult res(news_cat);256
229257 // If surfacing in not aggregated mode and set big-first-result setting to true, show first result in big
230 // We must have a URI258 sc::Category::SCPtr cat =
231 res.set_uri(item.uri);259 show_big_result && !meta.is_aggregated() && query_string.empty() ?
232 res.set_dnd_uri(item.uri);260 first_news_cat :
233261 news_cat;
234 // Set the rest of the attributes262
235 res.set_title(item.title);263 show_big_result = false;
236 res.set_art(item.art);264
237 res["published"] = sc::Variant(item.published);265 sc::CategorisedResult res(cat);
238 res["author"] = sc::Variant(item.author);266
239 res["summary"] = sc::Variant(item.summary);267 // We must have a URI
240 res["content"] = sc::Variant(item.content);268 res.set_uri(item.uri);
241 res["emblem"] = sc::Variant(scope_directory_+"/images/emblem.png");269 res.set_dnd_uri(item.uri);
242270
243 if (res.art().empty()) {271 // Set the rest of the attributes
244 res.set_art(scope_directory_ + "/icon.png");272 res.set_title(item.title);
245 }273 res.set_art(item.art);
246274 res["author"] = sc::Variant(item.author);
247 // if searched from aggregated, set formatted date to subtitle in case found keyword is related with news275 res["summary"] = sc::Variant(item.summary);
248 if (meta.is_aggregated()) {276 res["content"] = sc::Variant(item.content);
249 if (boost::starts_with(found_keyword, "news.")) {277 res["emblem"] = sc::Variant(emblem);
278
279 if (res.art().empty()) {
280 res.set_art(get_icon());
281 }
282
250 QString date = QString::fromStdString(item.published);283 QString date = QString::fromStdString(item.published);
284
251 if (!date.isEmpty()){285 if (!date.isEmpty()){
252 QDateTime ipostTime = QDateTime::fromString(date, Qt::RFC2822Date);286 QDateTime ipostTime = QDateTime::fromString(date, Qt::ISODate);
253 QString readeableTime = ipostTime.toString("hh:mm, d MMMM");287 QString readableTime = ipostTime.toString(QString::fromStdString(date_time_format));
254 res["subtitle"] = readeableTime.toStdString();288 res["published"] = readableTime.toStdString();
255 }289 }
256 }290
257 }291 // if searched from aggregated, set formatted date to subtitle in case found keyword is related with news
258292 if (meta.is_aggregated()) {
259 sc::VariantBuilder actions;293 if (boost::starts_with(found_keyword, "news.")) {
260 actions.add_tuple({294 res["subtitle"] = res["published"];
261 {"id", sc::Variant("open")},295 }
262 {"label", sc::Variant(_("Open"))},296 }
263 {"uri", sc::Variant(res.dnd_uri())}297
264 });298 sc::VariantBuilder actions;
265 res["actions"] = actions.end();299 actions.add_tuple({
266300 {"id", sc::Variant("open")},
267 // Push the result301 {"label", sc::Variant(_("Open"))},
268 if (!reply->push(res)) {302 {"uri", sc::Variant(res.dnd_uri())}
269 // If we fail to push, it means the query has been cancelled.303 });
270 // So don't continue;304
271 return;305 if (meta.is_aggregated()) {
272 }306 actions.add_tuple({
273 }307 {"id", sc::Variant("more")},
308 {"label", sc::Variant(_("More from ") + get_display_name())},
309 {"uri", sc::Variant(query.to_uri())}
310 });
311 }
312 res["actions"] = actions.end();
313
314 // Push the result
315 if (!reply->push(res)) {
316 // If we fail to push, it means the query has been cancelled.
317 // So don't continue;
318 return;
319 }
320 } // end if (!item.title.empty() && !item.uri.empty()) ...
321 } // end for (const auto &item : results) ...
322 } // end if (results.size > 0) ...
274323
275 } catch (domain_error &e) {324 } catch (domain_error &e) {
276 // Handle exceptions being thrown by the client API325 // Handle exceptions being thrown by the client API
@@ -279,3 +328,23 @@
279 }328 }
280}329}
281330
331string Query::get_icon() {
332 return scope_directory_ + "/" + mScopeConfig->value("ScopeConfig/Icon", "/icon.png").toString().toStdString();
333}
334
335string Query::get_display_name() {
336 return mScopeConfig->value("ScopeConfig/DisplayName", "").toString().toStdString();
337}
338
339string Query::get_emblem() {
340 return scope_directory_ + "/" + mScopeConfig->value("Appearance/Emblem", "/emblem.png").toString().toStdString();
341}
342
343string Query::get_date_time_format() {
344 return mScopeConfig->value("Appearance/DateTimeFormat", "hh:mm, d MMMM").toString().toStdString();
345}
346
347bool Query::get_big_first_result() {
348 return mScopeConfig->value("Appearance/BigFirstResult", false).toBool();
349}
350
282351
=== modified file 'src/scope/scope.cpp'
--- src/scope/scope.cpp 2015-03-25 03:17:53 +0000
+++ src/scope/scope.cpp 2015-08-08 22:18:29 +0000
@@ -1,4 +1,4 @@
1/* 1/*
2 * Copyright 2015 Canonical Ltd. 2 * Copyright 2015 Canonical Ltd.
3 * 3 *
4 * This program is free software; you can redistribute it and/or modify 4 * This program is free software; you can redistribute it and/or modify
@@ -31,21 +31,35 @@
31using namespace api;31using namespace api;
32using namespace scope;32using namespace scope;
3333
34void Scope::start(string const&) {34void Scope::start(string const& scope_id) {
35
36 scope_id_ = scope_id;
3537
36 setlocale(LC_ALL, "");38 setlocale(LC_ALL, "");
37 string translation_directory = ScopeBase::scope_directory()39 string translation_directory = ScopeBase::scope_directory()
38 + "/../share/locale/";40 + "/../share/locale/";
39 bindtextdomain(GETTEXT_PACKAGE, translation_directory.c_str());41 bindtextdomain(GETTEXT_PACKAGE, translation_directory.c_str());
42
43 loadScopeConfig();
40}44}
4145
42void Scope::stop() {46void Scope::stop() {
43}47}
4448
49void Scope::loadScopeConfig() {
50
51 std::string scope_config_file = ScopeBase::scope_directory() + "/" + scope_id_ + ".ini";
52 mScopeConfig = QSharedPointer<QSettings>::create(QString::fromStdString(scope_config_file), QSettings::IniFormat);
53
54 /*
55 qDebug() << "ALL KEYS:" << scope_config_->allKeys();
56 qDebug() << "ICON KEY:" << scope_config_->value("ScopeConfig/Icon").toString();
57 */
58}
59
45sc::SearchQueryBase::UPtr Scope::search(const sc::CannedQuery &query,60sc::SearchQueryBase::UPtr Scope::search(const sc::CannedQuery &query,
46 const sc::SearchMetadata &metadata) {61 const sc::SearchMetadata &search_metadata) {
47 // Boilerplate construction of Query62 return sc::SearchQueryBase::UPtr(new Query(query, search_metadata, scope_directory(), mScopeConfig));
48 return sc::SearchQueryBase::UPtr(new Query(query, metadata, scope_directory()));
49}63}
5064
51sc::PreviewQueryBase::UPtr Scope::preview(sc::Result const& result,65sc::PreviewQueryBase::UPtr Scope::preview(sc::Result const& result,

Subscribers

People subscribed via source and target branches