130
155
return rootDeptUrl;
133
Query::Query(const sc::CannedQuery &query, const sc::SearchMetadata &metadata, const string scope_directory) :
134
sc::SearchQueryBase(query, metadata),
136
scope_directory_(scope_directory) {
158
void Query::insert_keyword_feed(const string& keyword, const string& feed_url) {
159
if (!keyword.empty()) {
160
keyword_feeds_.insert( pair<string, string>(keyword, feed_url) );
164
pair<string,string> Query::find_url_for_keywords(const set<string>& search_keywords) {
165
for(const string& search_keyword : search_keywords) {
166
auto it = keyword_feeds_.find(search_keyword);
167
if (it != keyword_feeds_.end()) {
168
const string& found_url = it->second;
169
return std::pair<string, string>(search_keyword, found_url);
172
return std::pair<string, string>{};
175
Query::Query(const sc::CannedQuery &query,
176
const sc::SearchMetadata &search_metadata,
177
const string& scope_directory,
178
const QSharedPointer<QSettings>& scopeConfig)
179
: sc::SearchQueryBase(query, search_metadata)
181
, scope_directory_{scope_directory}
182
, mScopeConfig{scopeConfig} {
139
185
void Query::cancelled() {
140
186
client_.cancel();
144
189
void Query::run(sc::SearchReplyProxy const& reply) {
146
191
// Start by getting information about the query
147
192
const sc::CannedQuery &query(sc::SearchQueryBase::query());
153
198
QString deptFile = QString::fromStdString(scope_directory_) + "/feeds.json";
154
199
string feedUrl = getDepartments(deptFile, reply).toStdString(); // feedUrl has the root URL
156
// If the current dept ID is empty use the root URL otherwise use
157
// the dept ID, which should be a department feed URL
158
if (!query.department_id().empty()) {
159
feedUrl = query.department_id();
201
// Check if the search comes from an aggregator scope
202
const sc::SearchMetadata &meta(sc::SearchQueryBase::search_metadata());
203
string found_keyword; // this var will store the keyword related with a found url in case of agg. scope search.
204
if (meta.is_aggregated()) {
205
auto found_pair = find_url_for_keywords(meta.aggregated_keywords());
206
found_keyword = found_pair.first;
207
feedUrl = found_pair.second;
209
// If the current dept ID is empty use the root URL otherwise use
210
// the dept ID, which should be a department feed URL
211
if (!query.department_id().empty()) {
212
feedUrl = query.department_id();
162
216
if (feedUrl.empty()) {
168
222
vector<Client::Item> results = client_.getItems(feedUrl);
170
// Register a category for the forecast
224
// Register a category for the common news
171
225
auto news_cat = reply->register_category("news",
172
226
"", "", sc::CategoryRenderer(NEWS_LAYOUT));
174
// For each of the forecast days
175
for (const auto &item : results) {
177
// Filter by search term if we have one
178
if (!query_string.empty()) {
179
QString qry = QString::fromStdString(query_string);
180
QString title = QString::fromStdString(item.title);
181
QString summary = QString::fromStdString(item.summary);
182
QString content = QString::fromStdString(item.content);
184
if (!title.contains(qry, Qt::CaseInsensitive) &&
185
!summary.contains(qry, Qt::CaseInsensitive) &&
186
!content.contains(qry, Qt::CaseInsensitive)) {
227
auto first_news_cat = reply->register_category("first_news",
228
"", "", sc::CategoryRenderer(FIRST_NEWS_LAYOUT));
230
if (results.size() > 0) {
232
// Get common values for all results to avoid asking for them in every iteration
233
std::string emblem = get_emblem();
234
std::string date_time_format = get_date_time_format();
235
bool show_big_result = get_big_first_result();
237
// For each of the results vector items
238
for (const auto &item : results) {
240
// Filter by search term if we have one
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);
247
if (!title.contains(qry, Qt::CaseInsensitive) &&
248
!summary.contains(qry, Qt::CaseInsensitive) &&
249
!content.contains(qry, Qt::CaseInsensitive)) {
192
sc::CategorisedResult res(news_cat);
194
// We must have a URI
195
res.set_uri(item.uri);
196
res.set_dnd_uri(item.uri);
198
// Set the rest of the attributes
199
res.set_title(item.title);
200
res.set_art(item.art);
201
res["published"] = sc::Variant(item.published);
202
res["author"] = sc::Variant(item.author);
203
res["summary"] = sc::Variant(item.summary);
204
res["content"] = sc::Variant(item.content);
206
if (res.art().empty()) {
207
res.set_art(scope_directory_ + "/icon.png");
210
sc::VariantBuilder actions;
212
{"id", sc::Variant("open")},
213
{"label", sc::Variant(_("Open"))},
214
{"uri", sc::Variant(res.dnd_uri())}
216
res["actions"] = actions.end();
219
if (!reply->push(res)) {
220
// If we fail to push, it means the query has been cancelled.
221
// So don't continue;
254
// Create a result if having title at least
255
if (!item.title.empty() && !item.uri.empty()) {
257
// If surfacing in not aggregated mode and set big-first-result setting to true, show first result in big
258
sc::Category::SCPtr cat =
259
show_big_result && !meta.is_aggregated() && query_string.empty() ?
263
show_big_result = false;
265
sc::CategorisedResult res(cat);
267
// We must have a URI
268
res.set_uri(item.uri);
269
res.set_dnd_uri(item.uri);
271
// Set the rest of the attributes
272
res.set_title(item.title);
273
res.set_art(item.art);
274
res["author"] = sc::Variant(item.author);
275
res["summary"] = sc::Variant(item.summary);
276
res["content"] = sc::Variant(item.content);
277
res["emblem"] = sc::Variant(emblem);
279
if (res.art().empty()) {
280
res.set_art(get_icon());
283
QString date = QString::fromStdString(item.published);
285
if (!date.isEmpty()){
286
QDateTime ipostTime = QDateTime::fromString(date, Qt::ISODate);
287
QString readableTime = ipostTime.toString(QString::fromStdString(date_time_format));
288
res["published"] = readableTime.toStdString();
291
// if searched from aggregated, set formatted date to subtitle in case found keyword is related with news
292
if (meta.is_aggregated()) {
293
if (boost::starts_with(found_keyword, "news.")) {
294
res["subtitle"] = res["published"];
298
sc::VariantBuilder actions;
300
{"id", sc::Variant("open")},
301
{"label", sc::Variant(_("Open"))},
302
{"uri", sc::Variant(res.dnd_uri())}
305
if (meta.is_aggregated()) {
307
{"id", sc::Variant("more")},
308
{"label", sc::Variant(_("More from ") + get_display_name())},
309
{"uri", sc::Variant(query.to_uri())}
312
res["actions"] = actions.end();
315
if (!reply->push(res)) {
316
// If we fail to push, it means the query has been cancelled.
317
// So don't continue;
320
} // end if (!item.title.empty() && !item.uri.empty()) ...
321
} // end for (const auto &item : results) ...
322
} // end if (results.size > 0) ...
226
324
} catch (domain_error &e) {
227
325
// Handle exceptions being thrown by the client API