1
#include <boost/algorithm/string/trim.hpp>
3
#include <scope/localization.h>
4
#include <scope/query.h>
6
#include <unity/scopes/Annotation.h>
7
#include <unity/scopes/CategorisedResult.h>
8
#include <unity/scopes/CategoryRenderer.h>
9
#include <unity/scopes/QueryBase.h>
10
#include <unity/scopes/SearchReply.h>
15
namespace sc = unity::scopes;
16
namespace alg = boost::algorithm;
20
using namespace scope;
24
* Define the layout for the forecast results
26
* The icon size is small, and ask for the card layout
27
* itself to be horizontal. I.e. the text will be placed
30
const static string WEATHER_TEMPLATE =
35
"category-layout": "grid",
36
"card-layout": "horizontal",
44
"subtitle": "subtitle"
50
* Define the larger "current weather" layout.
52
* The icons are larger.
54
const static string CITY_TEMPLATE =
59
"category-layout": "grid",
67
"subtitle": "subtitle"
72
Query::Query(const sc::CannedQuery &query, const sc::SearchMetadata &metadata,
74
sc::SearchQueryBase(query, metadata), client_(config) {
77
void Query::cancelled() {
82
void Query::run(sc::SearchReplyProxy const& reply) {
84
// Start by getting information about the query
85
const sc::CannedQuery &query(sc::SearchQueryBase::query());
87
// Trim the query string of whitespace
88
string query_string = alg::trim_copy(query.query_string());
90
// the Client is the helper class that provides the results
91
// without mixing APIs and scopes code.
92
// Add your code to retreive xml, json, or any other kind of result
94
Client::Current current;
95
if (query_string.empty()) {
96
// If the string is empty, get the current weather for London
97
current = client_.weather("London,uk");
99
// otherwise, get the current weather for the search string
100
current = client_.weather(query_string);
103
// Build up the description for the city
104
stringstream ss(stringstream::in | stringstream::out);
105
ss << current.city.name << ", " << current.city.country;
107
// Register a category for the current weather, with the title we just built
108
auto location_cat = reply->register_category("current", ss.str(), "",
109
sc::CategoryRenderer(CITY_TEMPLATE));
112
// Create a single result for the current weather category
113
sc::CategorisedResult res(location_cat);
115
// We must have a URI
116
res.set_uri(to_string(current.city.id));
118
// Build up the description for the current weather
119
stringstream ss(stringstream::in | stringstream::out);
120
ss << setprecision(3) << current.weather.temp.cur;
122
res.set_title(ss.str());
124
// Set the rest of the attributes, art, description, etc
125
res.set_art(current.weather.icon);
126
res["subtitle"] = current.weather.description;
127
res["description"] = "A description of the result";
130
if (!reply->push(res)) {
131
// If we fail to push, it means the query has been cancelled.
132
// So don't continue;
137
Client::Forecast forecast;
138
if (query_string.empty()) {
139
// If there is no search string, get the forecast for London
140
forecast = client_.forecast_daily("London,uk");
142
// otherwise, get the forecast for the search string
143
forecast = client_.forecast_daily(query_string);
146
// Register a category for the forecast
147
auto forecast_cat = reply->register_category("forecast",
148
_("7 day forecast"), "", sc::CategoryRenderer(WEATHER_TEMPLATE));
150
// For each of the forecast days
151
for (const auto &weather : forecast.weather) {
153
sc::CategorisedResult res(forecast_cat);
155
// We must have a URI
156
res.set_uri(to_string(weather.id));
158
// Build the description for the result
159
stringstream ss(stringstream::in | stringstream::out);
160
ss << setprecision(3) << weather.temp.max;
162
ss << setprecision(3) << weather.temp.min;
164
res.set_title(ss.str());
166
// Set the rest of the attributes
167
res.set_art(weather.icon);
168
res["subtitle"] = weather.description;
169
res["description"] = "A description of the result";
172
if (!reply->push(res)) {
173
// If we fail to push, it means the query has been cancelled.
174
// So don't continue;
179
} catch (domain_error &e) {
180
// Handle exceptions being thrown by the client API
181
cerr << e.what() << endl;
182
reply->error(current_exception());