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 "chrome/browser/ui/app_list/search/mixer.h" | 5 #include "chrome/browser/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 "chrome/browser/ui/app_list/search/chrome_search_result.h" | |
14 #include "ui/app_list/search_provider.h" | 13 #include "ui/app_list/search_provider.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 const size_t kMaxMainGroupResults = 4; | 22 const size_t kMaxMainGroupResults = 4; |
23 const size_t kMaxWebstoreResults = 2; | 23 const size_t kMaxWebstoreResults = 2; |
24 const size_t kMaxPeopleResults = 2; | 24 const size_t kMaxPeopleResults = 2; |
25 | 25 |
26 // A value to indicate no max number of results limit. | 26 // A value to indicate no max number of results limit. |
27 const size_t kNoMaxResultsLimit = 0; | 27 const size_t kNoMaxResultsLimit = 0; |
28 | 28 |
29 void UpdateResult(const ChromeSearchResult& source, | 29 void UpdateResult(const SearchResult& source, |
30 ChromeSearchResult* target) { | 30 SearchResult* target) { |
31 target->set_title(source.title()); | 31 target->set_title(source.title()); |
32 target->set_title_tags(source.title_tags()); | 32 target->set_title_tags(source.title_tags()); |
33 target->set_details(source.details()); | 33 target->set_details(source.details()); |
34 target->set_details_tags(source.details_tags()); | 34 target->set_details_tags(source.details_tags()); |
35 } | 35 } |
36 | 36 |
37 } // namespace | 37 } // namespace |
38 | 38 |
39 Mixer::SortData::SortData() : result(NULL), score(0.0) { | 39 Mixer::SortData::SortData() : result(NULL), score(0.0) { |
40 } | 40 } |
41 | 41 |
42 Mixer::SortData::SortData(ChromeSearchResult* result, double score) | 42 Mixer::SortData::SortData(SearchResult* result, double score) |
43 : result(result), score(score) { | 43 : result(result), score(score) { |
44 } | 44 } |
45 | 45 |
46 bool Mixer::SortData::operator<(const SortData& other) const { | 46 bool Mixer::SortData::operator<(const SortData& other) const { |
47 // This data precedes (less than) |other| if it has higher score. | 47 // This data precedes (less than) |other| if it has higher score. |
48 return score > other.score; | 48 return score > other.score; |
49 } | 49 } |
50 | 50 |
51 // Used to group relevant providers together fox mixing their results. | 51 // Used to group relevant providers together fox mixing their results. |
52 class Mixer::Group { | 52 class Mixer::Group { |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
92 case PREFIX_SECONDARY: | 92 case PREFIX_SECONDARY: |
93 boost = 3.0; | 93 boost = 3.0; |
94 break; | 94 break; |
95 case UNKNOWN_RESULT: | 95 case UNKNOWN_RESULT: |
96 NOTREACHED() << "Unknown result in KnownResults?"; | 96 NOTREACHED() << "Unknown result in KnownResults?"; |
97 break; | 97 break; |
98 } | 98 } |
99 } | 99 } |
100 | 100 |
101 results_.push_back( | 101 results_.push_back( |
102 SortData(static_cast<ChromeSearchResult*>(*result_it), | 102 SortData(*result_it, (*result_it)->relevance() + boost)); |
103 (*result_it)->relevance() + boost)); | |
104 } | 103 } |
105 } | 104 } |
106 | 105 |
107 std::sort(results_.begin(), results_.end()); | 106 std::sort(results_.begin(), results_.end()); |
108 if (max_results_ != kNoMaxResultsLimit && results_.size() > max_results_) | 107 if (max_results_ != kNoMaxResultsLimit && results_.size() > max_results_) |
109 results_.resize(max_results_); | 108 results_.resize(max_results_); |
110 } | 109 } |
111 | 110 |
112 const SortedResults& results() const { return results_; } | 111 const SortedResults& results() const { return results_; } |
113 | 112 |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
175 std::sort(results.begin(), results.end()); | 174 std::sort(results.begin(), results.end()); |
176 RemoveDuplicates(&results); | 175 RemoveDuplicates(&results); |
177 if (results.size() > kMaxResults) | 176 if (results.size() > kMaxResults) |
178 results.resize(kMaxResults); | 177 results.resize(kMaxResults); |
179 | 178 |
180 Publish(results, ui_results_); | 179 Publish(results, ui_results_); |
181 } | 180 } |
182 | 181 |
183 void Mixer::Publish(const SortedResults& new_results, | 182 void Mixer::Publish(const SortedResults& new_results, |
184 AppListModel::SearchResults* ui_results) { | 183 AppListModel::SearchResults* ui_results) { |
185 typedef std::map<std::string, ChromeSearchResult*> IdToResultMap; | 184 typedef std::map<std::string, SearchResult*> IdToResultMap; |
186 | 185 |
187 // The following algorithm is used: | 186 // The following algorithm is used: |
188 // 1. Transform the |ui_results| list into an unordered map from result ID | 187 // 1. Transform the |ui_results| list into an unordered map from result ID |
189 // to item. | 188 // to item. |
190 // 2. Use the order of items in |new_results| to build an ordered list. If the | 189 // 2. Use the order of items in |new_results| to build an ordered list. If the |
191 // result IDs exist in the map, update and use the item in the map and delete | 190 // result IDs exist in the map, update and use the item in the map and delete |
192 // it from the map afterwards. Otherwise, clone new items from |new_results|. | 191 // it from the map afterwards. Otherwise, clone new items from |new_results|. |
193 // 3. Delete the objects remaining in the map as they are unused. | 192 // 3. Delete the objects remaining in the map as they are unused. |
194 | 193 |
195 // A map of the items in |ui_results| that takes ownership of the items. | 194 // A map of the items in |ui_results| that takes ownership of the items. |
196 IdToResultMap ui_results_map; | 195 IdToResultMap ui_results_map; |
197 for (size_t i = 0; i < ui_results->item_count(); ++i) { | 196 for (size_t i = 0; i < ui_results->item_count(); ++i) { |
198 ChromeSearchResult* ui_result = | 197 SearchResult* ui_result = ui_results->GetItemAt(i); |
199 static_cast<ChromeSearchResult*>(ui_results->GetItemAt(i)); | |
200 ui_results_map[ui_result->id()] = ui_result; | 198 ui_results_map[ui_result->id()] = ui_result; |
201 } | 199 } |
202 // We have to erase all results at once so that observers are notified with | 200 // We have to erase all results at once so that observers are notified with |
203 // meaningful indexes. | 201 // meaningful indexes. |
204 ui_results->RemoveAll(); | 202 ui_results->RemoveAll(); |
205 | 203 |
206 // Add items back to |ui_results| in the order of |new_results|. | 204 // Add items back to |ui_results| in the order of |new_results|. |
207 for (size_t i = 0; i < new_results.size(); ++i) { | 205 for (size_t i = 0; i < new_results.size(); ++i) { |
208 ChromeSearchResult* new_result = new_results[i].result; | 206 SearchResult* new_result = new_results[i].result; |
209 IdToResultMap::const_iterator ui_result_it = | 207 IdToResultMap::const_iterator ui_result_it = |
210 ui_results_map.find(new_result->id()); | 208 ui_results_map.find(new_result->id()); |
211 if (ui_result_it != ui_results_map.end()) { | 209 if (ui_result_it != ui_results_map.end()) { |
212 // Update and use the old result if it exists. | 210 // Update and use the old result if it exists. |
213 ChromeSearchResult* ui_result = ui_result_it->second; | 211 SearchResult* ui_result = ui_result_it->second; |
214 UpdateResult(*new_result, ui_result); | 212 UpdateResult(*new_result, ui_result); |
215 | 213 |
216 // |ui_results| takes back ownership from |ui_results_map| here. | 214 // |ui_results| takes back ownership from |ui_results_map| here. |
217 ui_results->Add(ui_result); | 215 ui_results->Add(ui_result); |
218 | 216 |
219 // Remove the item from the map so that it ends up only with unused | 217 // Remove the item from the map so that it ends up only with unused |
220 // results. | 218 // results. |
221 ui_results_map.erase(ui_result->id()); | 219 ui_results_map.erase(ui_result->id()); |
222 } else { | 220 } else { |
223 // Copy the result from |new_results| otherwise. | 221 // Copy the result from |new_results| otherwise. |
(...skipping 29 matching lines...) Expand all Loading... |
253 | 251 |
254 void Mixer::FetchResults(const KnownResults& known_results) { | 252 void Mixer::FetchResults(const KnownResults& known_results) { |
255 for (Groups::iterator group_it = groups_.begin(); | 253 for (Groups::iterator group_it = groups_.begin(); |
256 group_it != groups_.end(); | 254 group_it != groups_.end(); |
257 ++group_it) { | 255 ++group_it) { |
258 (*group_it)->FetchResults(known_results); | 256 (*group_it)->FetchResults(known_results); |
259 } | 257 } |
260 } | 258 } |
261 | 259 |
262 } // namespace app_list | 260 } // namespace app_list |
OLD | NEW |