~gary-wzl77/+junk/newproperty

« back to all changes in this revision

Viewing changes to src/scope/query.cpp

  • Committer: Gary.Wzl
  • Date: 2015-08-31 09:23:43 UTC
  • Revision ID: gary.wang@canonical.com-20150831092343-x7coc5ukz9yelqjn
Init repo

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include <boost/algorithm/string/trim.hpp>
 
2
 
 
3
#include <scope/localization.h>
 
4
#include <scope/query.h>
 
5
 
 
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>
 
11
 
 
12
#include <iomanip>
 
13
#include <sstream>
 
14
 
 
15
namespace sc = unity::scopes;
 
16
namespace alg = boost::algorithm;
 
17
 
 
18
using namespace std;
 
19
using namespace api;
 
20
using namespace scope;
 
21
 
 
22
 
 
23
/**
 
24
 * Define the layout for the forecast results
 
25
 *
 
26
 * The icon size is small, and ask for the card layout
 
27
 * itself to be horizontal. I.e. the text will be placed
 
28
 * next to the image.
 
29
 */
 
30
const static string WEATHER_TEMPLATE =
 
31
        R"(
 
32
{
 
33
        "schema-version": 1,
 
34
        "template": {
 
35
        "category-layout": "grid",
 
36
        "card-layout": "horizontal",
 
37
        "card-size": "small"
 
38
        },
 
39
        "components": {
 
40
        "title": "title",
 
41
        "art" : {
 
42
        "field": "art"
 
43
        },
 
44
        "subtitle": "subtitle"
 
45
        }
 
46
        }
 
47
        )";
 
48
 
 
49
/**
 
50
 * Define the larger "current weather" layout.
 
51
 *
 
52
 * The icons are larger.
 
53
 */
 
54
const static string CITY_TEMPLATE =
 
55
        R"(
 
56
{
 
57
        "schema-version": 1,
 
58
        "template": {
 
59
        "category-layout": "grid",
 
60
        "card-size": "medium"
 
61
        },
 
62
        "components": {
 
63
        "title": "title",
 
64
        "art" : {
 
65
        "field": "art"
 
66
        },
 
67
        "subtitle": "subtitle"
 
68
        }
 
69
        }
 
70
        )";
 
71
 
 
72
Query::Query(const sc::CannedQuery &query, const sc::SearchMetadata &metadata,
 
73
             Config::Ptr config) :
 
74
    sc::SearchQueryBase(query, metadata), client_(config) {
 
75
}
 
76
 
 
77
void Query::cancelled() {
 
78
    client_.cancel();
 
79
}
 
80
 
 
81
 
 
82
void Query::run(sc::SearchReplyProxy const& reply) {
 
83
    try {
 
84
        // Start by getting information about the query
 
85
        const sc::CannedQuery &query(sc::SearchQueryBase::query());
 
86
 
 
87
        // Trim the query string of whitespace
 
88
        string query_string = alg::trim_copy(query.query_string());
 
89
 
 
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
 
93
        // in the client.
 
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");
 
98
        } else {
 
99
            // otherwise, get the current weather for the search string
 
100
            current = client_.weather(query_string);
 
101
        }
 
102
 
 
103
        // Build up the description for the city
 
104
        stringstream ss(stringstream::in | stringstream::out);
 
105
        ss << current.city.name << ", " << current.city.country;
 
106
 
 
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));
 
110
 
 
111
        {
 
112
            // Create a single result for the current weather category
 
113
            sc::CategorisedResult res(location_cat);
 
114
 
 
115
            // We must have a URI
 
116
            res.set_uri(to_string(current.city.id));
 
117
 
 
118
            // Build up the description for the current weather
 
119
            stringstream ss(stringstream::in | stringstream::out);
 
120
            ss << setprecision(3) << current.weather.temp.cur;
 
121
            ss << "°C";
 
122
            res.set_title(ss.str());
 
123
 
 
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";
 
128
 
 
129
            // Push 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;
 
133
                return;
 
134
            }
 
135
        }
 
136
 
 
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");
 
141
        } else {
 
142
            // otherwise, get the forecast for the search string
 
143
            forecast = client_.forecast_daily(query_string);
 
144
        }
 
145
 
 
146
        // Register a category for the forecast
 
147
        auto forecast_cat = reply->register_category("forecast",
 
148
                                                     _("7 day forecast"), "", sc::CategoryRenderer(WEATHER_TEMPLATE));
 
149
 
 
150
        // For each of the forecast days
 
151
        for (const auto &weather : forecast.weather) {
 
152
            // Create a result
 
153
            sc::CategorisedResult res(forecast_cat);
 
154
 
 
155
            // We must have a URI
 
156
            res.set_uri(to_string(weather.id));
 
157
 
 
158
            // Build the description for the result
 
159
            stringstream ss(stringstream::in | stringstream::out);
 
160
            ss << setprecision(3) << weather.temp.max;
 
161
            ss << "°C to ";
 
162
            ss << setprecision(3) << weather.temp.min;
 
163
            ss << "°C";
 
164
            res.set_title(ss.str());
 
165
 
 
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";
 
170
 
 
171
            // Push 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;
 
175
                return;
 
176
            }
 
177
        }
 
178
 
 
179
    } catch (domain_error &e) {
 
180
        // Handle exceptions being thrown by the client API
 
181
        cerr << e.what() << endl;
 
182
        reply->error(current_exception());
 
183
    }
 
184
}
 
185