| 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> |
| (...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 173 // group has a soft maximum of 4 results. (Otherwise, the People result | 173 // group has a soft maximum of 4 results. (Otherwise, the People result |
| 174 // would not be seen at all once the result list is truncated.) | 174 // would not be seen at all once the result list is truncated.) |
| 175 std::sort(results.begin() + original_size, results.end()); | 175 std::sort(results.begin() + original_size, results.end()); |
| 176 } | 176 } |
| 177 | 177 |
| 178 Publish(results, ui_results_); | 178 Publish(results, ui_results_); |
| 179 } | 179 } |
| 180 | 180 |
| 181 void Mixer::Publish(const SortedResults& new_results, | 181 void Mixer::Publish(const SortedResults& new_results, |
| 182 AppListModel::SearchResults* ui_results) { | 182 AppListModel::SearchResults* ui_results) { |
| 183 typedef std::map<std::string, SearchResult*> IdToResultMap; | |
| 184 | |
| 185 // The following algorithm is used: | 183 // The following algorithm is used: |
| 186 // 1. Transform the |ui_results| list into an unordered map from result ID | 184 // 1. Transform the |ui_results| list into an unordered map from result ID |
| 187 // to item. | 185 // to item. |
| 188 // 2. Use the order of items in |new_results| to build an ordered list. If the | 186 // 2. Use the order of items in |new_results| to build an ordered list. If the |
| 189 // result IDs exist in the map, update and use the item in the map and delete | 187 // result IDs exist in the map, update and use the item in the map and delete |
| 190 // it from the map afterwards. Otherwise, clone new items from |new_results|. | 188 // it from the map afterwards. Otherwise, clone new items from |new_results|. |
| 191 // 3. Delete the objects remaining in the map as they are unused. | 189 // 3. Delete the objects remaining in the map as they are unused. |
| 192 | 190 |
| 193 // A map of the items in |ui_results| that takes ownership of the items. | |
| 194 IdToResultMap ui_results_map; | |
| 195 for (SearchResult* ui_result : *ui_results) | |
| 196 ui_results_map[ui_result->id()] = ui_result; | |
| 197 // We have to erase all results at once so that observers are notified with | 191 // We have to erase all results at once so that observers are notified with |
| 198 // meaningful indexes. | 192 // meaningful indexes. |
| 199 ui_results->RemoveAll(); | 193 auto current_results = ui_results->RemoveAll(); |
| 194 std::map<std::string, std::unique_ptr<SearchResult>> ui_results_map; |
| 195 for (std::unique_ptr<SearchResult>& ui_result : current_results) |
| 196 ui_results_map[ui_result->id()] = std::move(ui_result); |
| 200 | 197 |
| 201 // Add items back to |ui_results| in the order of |new_results|. | 198 // Add items back to |ui_results| in the order of |new_results|. |
| 202 for (const SortData& sort_data : new_results) { | 199 for (const SortData& sort_data : new_results) { |
| 203 const SearchResult& new_result = *sort_data.result; | 200 const SearchResult& new_result = *sort_data.result; |
| 204 IdToResultMap::const_iterator ui_result_it = | 201 auto ui_result_it = ui_results_map.find(new_result.id()); |
| 205 ui_results_map.find(new_result.id()); | |
| 206 if (ui_result_it != ui_results_map.end()) { | 202 if (ui_result_it != ui_results_map.end()) { |
| 207 // Update and use the old result if it exists. | 203 // Update and use the old result if it exists. |
| 208 SearchResult* ui_result = ui_result_it->second; | 204 std::unique_ptr<SearchResult> ui_result = std::move(ui_result_it->second); |
| 209 UpdateResult(new_result, ui_result); | 205 UpdateResult(new_result, ui_result.get()); |
| 210 ui_result->set_relevance(sort_data.score); | 206 ui_result->set_relevance(sort_data.score); |
| 211 | 207 |
| 212 // |ui_results| takes back ownership from |ui_results_map| here. | 208 ui_results->Add(std::move(ui_result)); |
| 213 ui_results->Add(ui_result); | |
| 214 | 209 |
| 215 // Remove the item from the map so that it ends up only with unused | 210 // Remove the item from the map so that it ends up only with unused |
| 216 // results. | 211 // results. |
| 217 ui_results_map.erase(ui_result->id()); | 212 ui_results_map.erase(ui_result_it); |
| 218 } else { | 213 } else { |
| 219 std::unique_ptr<SearchResult> result_copy = new_result.Duplicate(); | 214 std::unique_ptr<SearchResult> result_copy = new_result.Duplicate(); |
| 220 result_copy->set_relevance(sort_data.score); | 215 result_copy->set_relevance(sort_data.score); |
| 221 // Copy the result from |new_results| otherwise. | 216 // Copy the result from |new_results| otherwise. |
| 222 ui_results->Add(result_copy.release()); | 217 ui_results->Add(std::move(result_copy)); |
| 223 } | 218 } |
| 224 } | 219 } |
| 225 | 220 |
| 226 // Delete the results remaining in the map as they are not in the new results. | 221 // Any remaining results in |ui_results_map| will be automatically deleted. |
| 227 for (const auto& ui_result : ui_results_map) { | |
| 228 delete ui_result.second; | |
| 229 } | |
| 230 } | 222 } |
| 231 | 223 |
| 232 void Mixer::RemoveDuplicates(SortedResults* results) { | 224 void Mixer::RemoveDuplicates(SortedResults* results) { |
| 233 SortedResults final; | 225 SortedResults final; |
| 234 final.reserve(results->size()); | 226 final.reserve(results->size()); |
| 235 | 227 |
| 236 std::set<std::string> id_set; | 228 std::set<std::string> id_set; |
| 237 for (const SortData& sort_data : *results) { | 229 for (const SortData& sort_data : *results) { |
| 238 const std::string& id = sort_data.result->id(); | 230 const std::string& id = sort_data.result->id(); |
| 239 if (id_set.find(id) != id_set.end()) | 231 if (id_set.find(id) != id_set.end()) |
| 240 continue; | 232 continue; |
| 241 | 233 |
| 242 id_set.insert(id); | 234 id_set.insert(id); |
| 243 final.push_back(sort_data); | 235 final.push_back(sort_data); |
| 244 } | 236 } |
| 245 | 237 |
| 246 results->swap(final); | 238 results->swap(final); |
| 247 } | 239 } |
| 248 | 240 |
| 249 void Mixer::FetchResults(bool is_voice_query, | 241 void Mixer::FetchResults(bool is_voice_query, |
| 250 const KnownResults& known_results) { | 242 const KnownResults& known_results) { |
| 251 for (auto* group : groups_) | 243 for (auto* group : groups_) |
| 252 group->FetchResults(is_voice_query, known_results); | 244 group->FetchResults(is_voice_query, known_results); |
| 253 } | 245 } |
| 254 | 246 |
| 255 } // namespace app_list | 247 } // namespace app_list |
| OLD | NEW |