OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ui/app_list/search/mixer.h" | 5 #include "ui/app_list/search/mixer.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <map> | 8 #include <map> |
9 #include <set> | 9 #include <set> |
10 #include <string> | 10 #include <string> |
11 #include <vector> | 11 #include <vector> |
12 | 12 |
13 #include "ui/app_list/search_provider.h" | 13 #include "ui/app_list/search_provider.h" |
14 #include "ui/app_list/search_result.h" | 14 #include "ui/app_list/search_result.h" |
15 | 15 |
16 namespace app_list { | 16 namespace app_list { |
17 | 17 |
18 namespace { | 18 namespace { |
19 | 19 |
20 // Maximum number of results to show. | 20 // Maximum number of results to show. |
21 const size_t kMaxResults = 6; | 21 const size_t kMaxResults = 6; |
22 | 22 |
23 // A value to indicate no max number of results limit. | |
24 const size_t kNoMaxResultsLimit = 0; | |
25 | |
26 void UpdateResult(const SearchResult& source, SearchResult* target) { | 23 void UpdateResult(const SearchResult& source, SearchResult* target) { |
27 target->set_display_type(source.display_type()); | 24 target->set_display_type(source.display_type()); |
28 target->set_title(source.title()); | 25 target->set_title(source.title()); |
29 target->set_title_tags(source.title_tags()); | 26 target->set_title_tags(source.title_tags()); |
30 target->set_details(source.details()); | 27 target->set_details(source.details()); |
31 target->set_details_tags(source.details_tags()); | 28 target->set_details_tags(source.details_tags()); |
32 } | 29 } |
33 | 30 |
34 } // namespace | 31 } // namespace |
35 | 32 |
36 Mixer::SortData::SortData() : result(NULL), score(0.0) { | 33 Mixer::SortData::SortData() : result(NULL), score(0.0) { |
37 } | 34 } |
38 | 35 |
39 Mixer::SortData::SortData(SearchResult* result, double score) | 36 Mixer::SortData::SortData(SearchResult* result, double score) |
40 : result(result), score(score) { | 37 : result(result), score(score) { |
41 } | 38 } |
42 | 39 |
43 bool Mixer::SortData::operator<(const SortData& other) const { | 40 bool Mixer::SortData::operator<(const SortData& other) const { |
44 // This data precedes (less than) |other| if it has higher score. | 41 // This data precedes (less than) |other| if it has higher score. |
45 return score > other.score; | 42 return score > other.score; |
46 } | 43 } |
47 | 44 |
48 // Used to group relevant providers together fox mixing their results. | 45 // Used to group relevant providers together for mixing their results. |
49 class Mixer::Group { | 46 class Mixer::Group { |
50 public: | 47 public: |
51 Group(size_t max_results, double boost) | 48 Group(size_t max_results, double boost) |
52 : max_results_(max_results), boost_(boost) {} | 49 : max_results_(max_results), boost_(boost) {} |
53 ~Group() {} | 50 ~Group() {} |
54 | 51 |
55 void AddProvider(SearchProvider* provider) { providers_.push_back(provider); } | 52 void AddProvider(SearchProvider* provider) { providers_.push_back(provider); } |
56 | 53 |
57 void FetchResults(bool is_voice_query, const KnownResults& known_results) { | 54 void FetchResults(bool is_voice_query, const KnownResults& known_results) { |
58 results_.clear(); | 55 results_.clear(); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
91 | 88 |
92 // If this is a voice query, voice results receive a massive boost. | 89 // If this is a voice query, voice results receive a massive boost. |
93 if (is_voice_query && result->voice_result()) | 90 if (is_voice_query && result->voice_result()) |
94 boost += 4.0; | 91 boost += 4.0; |
95 | 92 |
96 results_.push_back(SortData(result, relevance + boost)); | 93 results_.push_back(SortData(result, relevance + boost)); |
97 } | 94 } |
98 } | 95 } |
99 | 96 |
100 std::sort(results_.begin(), results_.end()); | 97 std::sort(results_.begin(), results_.end()); |
101 if (max_results_ != kNoMaxResultsLimit && results_.size() > max_results_) | |
102 results_.resize(max_results_); | |
103 } | 98 } |
104 | 99 |
105 const SortedResults& results() const { return results_; } | 100 const SortedResults& results() const { return results_; } |
106 | 101 |
| 102 size_t max_results() const { return max_results_; } |
| 103 |
107 private: | 104 private: |
108 typedef std::vector<SearchProvider*> Providers; | 105 typedef std::vector<SearchProvider*> Providers; |
109 const size_t max_results_; | 106 const size_t max_results_; |
110 const double boost_; | 107 const double boost_; |
111 | 108 |
112 Providers providers_; // Not owned. | 109 Providers providers_; // Not owned. |
113 SortedResults results_; | 110 SortedResults results_; |
114 | 111 |
115 DISALLOW_COPY_AND_ASSIGN(Group); | 112 DISALLOW_COPY_AND_ASSIGN(Group); |
116 }; | 113 }; |
(...skipping 22 matching lines...) Expand all Loading... |
139 groups_[group_id]->AddProvider(provider); | 136 groups_[group_id]->AddProvider(provider); |
140 } | 137 } |
141 | 138 |
142 void Mixer::MixAndPublish(bool is_voice_query, | 139 void Mixer::MixAndPublish(bool is_voice_query, |
143 const KnownResults& known_results) { | 140 const KnownResults& known_results) { |
144 FetchResults(is_voice_query, known_results); | 141 FetchResults(is_voice_query, known_results); |
145 | 142 |
146 SortedResults results; | 143 SortedResults results; |
147 results.reserve(kMaxResults); | 144 results.reserve(kMaxResults); |
148 | 145 |
149 // Add results from non-omnibox groups first. | 146 // Add results from non-omnibox groups first. Limit to the maximum number of |
| 147 // results in each group. |
150 for (size_t i = 0; i < groups_.size(); ++i) { | 148 for (size_t i = 0; i < groups_.size(); ++i) { |
151 if (!has_omnibox_group_ || i != omnibox_group_) { | 149 if (!has_omnibox_group_ || i != omnibox_group_) { |
152 const Group& group = *groups_[i]; | 150 const Group& group = *groups_[i]; |
| 151 size_t num_results = |
| 152 std::min(group.results().size(), group.max_results()); |
153 results.insert(results.end(), group.results().begin(), | 153 results.insert(results.end(), group.results().begin(), |
154 group.results().end()); | 154 group.results().begin() + num_results); |
155 } | 155 } |
156 } | 156 } |
157 | 157 |
158 // Collapse duplicate apps from local and web store. | 158 // Collapse duplicate apps from local and web store. |
159 RemoveDuplicates(&results); | 159 RemoveDuplicates(&results); |
160 | 160 |
161 // Fill the remaining slots with omnibox results. Always add at least one | 161 // Fill the remaining slots with omnibox results. Always add at least one |
162 // omnibox result (even if there are no more slots; if we over-fill the | 162 // omnibox result (even if there are no more slots; if we over-fill the |
163 // vector, the web store and people results will be removed in a later step). | 163 // vector, the web store and people results will be removed in a later step). |
| 164 // Note: max_results() is ignored for the omnibox group. |
164 if (has_omnibox_group_) { | 165 if (has_omnibox_group_) { |
165 CHECK_LT(omnibox_group_, groups_.size()); | 166 CHECK_LT(omnibox_group_, groups_.size()); |
166 const Group& omnibox_group = *groups_[omnibox_group_]; | 167 const Group& omnibox_group = *groups_[omnibox_group_]; |
167 const size_t omnibox_results = std::min( | 168 const size_t omnibox_results = std::min( |
168 omnibox_group.results().size(), | 169 omnibox_group.results().size(), |
169 results.size() < kMaxResults ? kMaxResults - results.size() : 1); | 170 results.size() < kMaxResults ? kMaxResults - results.size() : 1); |
170 results.insert(results.end(), omnibox_group.results().begin(), | 171 results.insert(results.end(), omnibox_group.results().begin(), |
171 omnibox_group.results().begin() + omnibox_results); | 172 omnibox_group.results().begin() + omnibox_results); |
172 } | 173 } |
173 | 174 |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
247 results->swap(final); | 248 results->swap(final); |
248 } | 249 } |
249 | 250 |
250 void Mixer::FetchResults(bool is_voice_query, | 251 void Mixer::FetchResults(bool is_voice_query, |
251 const KnownResults& known_results) { | 252 const KnownResults& known_results) { |
252 for (auto* group : groups_) | 253 for (auto* group : groups_) |
253 group->FetchResults(is_voice_query, known_results); | 254 group->FetchResults(is_voice_query, known_results); |
254 } | 255 } |
255 | 256 |
256 } // namespace app_list | 257 } // namespace app_list |
OLD | NEW |