| 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
|
|
|