Index: ui/app_list/search/mixer.cc |
diff --git a/ui/app_list/search/mixer.cc b/ui/app_list/search/mixer.cc |
deleted file mode 100644 |
index d4302907ec1b2f95e39dd96e9cb374d7108ac504..0000000000000000000000000000000000000000 |
--- a/ui/app_list/search/mixer.cc |
+++ /dev/null |
@@ -1,256 +0,0 @@ |
-// Copyright 2013 The Chromium Authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
- |
-#include "ui/app_list/search/mixer.h" |
- |
-#include <algorithm> |
-#include <map> |
-#include <set> |
-#include <string> |
-#include <vector> |
- |
-#include "ui/app_list/search_provider.h" |
-#include "ui/app_list/search_result.h" |
- |
-namespace app_list { |
- |
-namespace { |
- |
-// Maximum number of results to show. |
-const size_t kMaxResults = 6; |
-const size_t kMaxMainGroupResults = 4; |
-const size_t kMaxWebstoreResults = 2; |
-const size_t kMaxPeopleResults = 2; |
- |
-// A value to indicate no max number of results limit. |
-const size_t kNoMaxResultsLimit = 0; |
- |
-void UpdateResult(const SearchResult& source, SearchResult* target) { |
- target->set_title(source.title()); |
- target->set_title_tags(source.title_tags()); |
- target->set_details(source.details()); |
- target->set_details_tags(source.details_tags()); |
-} |
- |
-} // namespace |
- |
-Mixer::SortData::SortData() : result(NULL), score(0.0) { |
-} |
- |
-Mixer::SortData::SortData(SearchResult* result, double score) |
- : result(result), score(score) { |
-} |
- |
-bool Mixer::SortData::operator<(const SortData& other) const { |
- // This data precedes (less than) |other| if it has higher score. |
- return score > other.score; |
-} |
- |
-// Used to group relevant providers together fox mixing their results. |
-class Mixer::Group { |
- public: |
- Group(size_t max_results, double boost) |
- : max_results_(max_results), boost_(boost) {} |
- ~Group() {} |
- |
- void AddProvider(SearchProvider* provider) { providers_.push_back(provider); } |
- |
- void FetchResults(const KnownResults& known_results) { |
- results_.clear(); |
- |
- for (Providers::const_iterator provider_it = providers_.begin(); |
- provider_it != providers_.end(); |
- ++provider_it) { |
- for (SearchProvider::Results::const_iterator result_it = |
- (*provider_it)->results().begin(); |
- result_it != (*provider_it)->results().end(); |
- ++result_it) { |
- DCHECK_GE((*result_it)->relevance(), 0.0); |
- DCHECK_LE((*result_it)->relevance(), 1.0); |
- DCHECK(!(*result_it)->id().empty()); |
- |
- double boost = boost_; |
- KnownResults::const_iterator known_it = |
- known_results.find((*result_it)->id()); |
- if (known_it != known_results.end()) { |
- switch (known_it->second) { |
- case PERFECT_PRIMARY: |
- boost = 4.0; |
- break; |
- case PREFIX_PRIMARY: |
- boost = 3.75; |
- break; |
- case PERFECT_SECONDARY: |
- boost = 3.25; |
- break; |
- case PREFIX_SECONDARY: |
- boost = 3.0; |
- break; |
- case UNKNOWN_RESULT: |
- NOTREACHED() << "Unknown result in KnownResults?"; |
- break; |
- } |
- } |
- |
- results_.push_back( |
- SortData(*result_it, (*result_it)->relevance() + boost)); |
- } |
- } |
- |
- std::sort(results_.begin(), results_.end()); |
- if (max_results_ != kNoMaxResultsLimit && results_.size() > max_results_) |
- results_.resize(max_results_); |
- } |
- |
- const SortedResults& results() const { return results_; } |
- |
- private: |
- typedef std::vector<SearchProvider*> Providers; |
- const size_t max_results_; |
- const double boost_; |
- |
- Providers providers_; // Not owned. |
- SortedResults results_; |
- |
- DISALLOW_COPY_AND_ASSIGN(Group); |
-}; |
- |
-Mixer::Mixer(AppListModel::SearchResults* ui_results) |
- : ui_results_(ui_results) { |
-} |
-Mixer::~Mixer() { |
-} |
- |
-void Mixer::Init() { |
- groups_.push_back(new Group(kMaxMainGroupResults, 3.0)); |
- groups_.push_back(new Group(kNoMaxResultsLimit, 2.0)); |
- groups_.push_back(new Group(kMaxWebstoreResults, 1.0)); |
- groups_.push_back(new Group(kMaxPeopleResults, 0.0)); |
-} |
- |
-void Mixer::AddProviderToGroup(GroupId group, SearchProvider* provider) { |
- size_t group_index = static_cast<size_t>(group); |
- groups_[group_index]->AddProvider(provider); |
-} |
- |
-void Mixer::MixAndPublish(const KnownResults& known_results) { |
- FetchResults(known_results); |
- |
- SortedResults results; |
- results.reserve(kMaxResults); |
- |
- // Adds main group and web store results first. |
- results.insert(results.end(), |
- groups_[MAIN_GROUP]->results().begin(), |
- groups_[MAIN_GROUP]->results().end()); |
- results.insert(results.end(), |
- groups_[WEBSTORE_GROUP]->results().begin(), |
- groups_[WEBSTORE_GROUP]->results().end()); |
- results.insert(results.end(), |
- groups_[PEOPLE_GROUP]->results().begin(), |
- groups_[PEOPLE_GROUP]->results().end()); |
- |
- // Collapse duplicate apps from local and web store. |
- RemoveDuplicates(&results); |
- |
- DCHECK_GE(kMaxResults, results.size()); |
- size_t remaining_slots = kMaxResults - results.size(); |
- |
- // Reserves at least one slot for the omnibox result. If there is no available |
- // slot for omnibox results, removes the last one from web store. |
- const size_t omnibox_results = groups_[OMNIBOX_GROUP]->results().size(); |
- if (!remaining_slots && omnibox_results) |
- results.pop_back(); |
- |
- remaining_slots = std::min(kMaxResults - results.size(), omnibox_results); |
- results.insert(results.end(), |
- groups_[OMNIBOX_GROUP]->results().begin(), |
- groups_[OMNIBOX_GROUP]->results().begin() + remaining_slots); |
- |
- std::sort(results.begin(), results.end()); |
- RemoveDuplicates(&results); |
- if (results.size() > kMaxResults) |
- results.resize(kMaxResults); |
- |
- Publish(results, ui_results_); |
-} |
- |
-void Mixer::Publish(const SortedResults& new_results, |
- AppListModel::SearchResults* ui_results) { |
- typedef std::map<std::string, SearchResult*> IdToResultMap; |
- |
- // The following algorithm is used: |
- // 1. Transform the |ui_results| list into an unordered map from result ID |
- // to item. |
- // 2. Use the order of items in |new_results| to build an ordered list. If the |
- // result IDs exist in the map, update and use the item in the map and delete |
- // it from the map afterwards. Otherwise, clone new items from |new_results|. |
- // 3. Delete the objects remaining in the map as they are unused. |
- |
- // A map of the items in |ui_results| that takes ownership of the items. |
- IdToResultMap ui_results_map; |
- for (size_t i = 0; i < ui_results->item_count(); ++i) { |
- SearchResult* ui_result = ui_results->GetItemAt(i); |
- ui_results_map[ui_result->id()] = ui_result; |
- } |
- // We have to erase all results at once so that observers are notified with |
- // meaningful indexes. |
- ui_results->RemoveAll(); |
- |
- // Add items back to |ui_results| in the order of |new_results|. |
- for (size_t i = 0; i < new_results.size(); ++i) { |
- SearchResult* new_result = new_results[i].result; |
- IdToResultMap::const_iterator ui_result_it = |
- ui_results_map.find(new_result->id()); |
- if (ui_result_it != ui_results_map.end()) { |
- // Update and use the old result if it exists. |
- SearchResult* ui_result = ui_result_it->second; |
- UpdateResult(*new_result, ui_result); |
- |
- // |ui_results| takes back ownership from |ui_results_map| here. |
- ui_results->Add(ui_result); |
- |
- // Remove the item from the map so that it ends up only with unused |
- // results. |
- ui_results_map.erase(ui_result->id()); |
- } else { |
- // Copy the result from |new_results| otherwise. |
- ui_results->Add(new_result->Duplicate().release()); |
- } |
- } |
- |
- // Delete the results remaining in the map as they are not in the new results. |
- for (IdToResultMap::const_iterator ui_result_it = ui_results_map.begin(); |
- ui_result_it != ui_results_map.end(); |
- ++ui_result_it) { |
- delete ui_result_it->second; |
- } |
-} |
- |
-void Mixer::RemoveDuplicates(SortedResults* results) { |
- SortedResults final; |
- final.reserve(results->size()); |
- |
- std::set<std::string> id_set; |
- for (SortedResults::iterator it = results->begin(); it != results->end(); |
- ++it) { |
- const std::string& id = it->result->id(); |
- if (id_set.find(id) != id_set.end()) |
- continue; |
- |
- id_set.insert(id); |
- final.push_back(*it); |
- } |
- |
- results->swap(final); |
-} |
- |
-void Mixer::FetchResults(const KnownResults& known_results) { |
- for (Groups::iterator group_it = groups_.begin(); group_it != groups_.end(); |
- ++group_it) { |
- (*group_it)->FetchResults(known_results); |
- } |
-} |
- |
-} // namespace app_list |