Temporarily re-enabling SizeAfterPrefChange test with traces (this time for Linux...
[chromium-blink-merge.git] / chrome / browser / ui / bookmarks / recently_used_folders_combo_model.cc
blob09709cf9301cfe0328bdd6f28876b9257beaa063
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/ui/bookmarks/recently_used_folders_combo_model.h"
7 #include "components/bookmarks/browser/bookmark_model.h"
8 #include "components/bookmarks/browser/bookmark_utils.h"
9 #include "content/public/browser/user_metrics.h"
10 #include "grit/generated_resources.h"
11 #include "ui/base/l10n/l10n_util.h"
12 #include "ui/base/models/combobox_model_observer.h"
14 namespace {
16 // Max number of most recently used folders.
17 const size_t kMaxMRUFolders = 5;
19 } // namespace
21 struct RecentlyUsedFoldersComboModel::Item {
22 enum Type {
23 TYPE_NODE,
24 TYPE_SEPARATOR,
25 TYPE_CHOOSE_ANOTHER_FOLDER
28 Item(const BookmarkNode* node, Type type);
29 ~Item();
31 bool operator==(const Item& item) const;
33 const BookmarkNode* node;
34 Type type;
37 RecentlyUsedFoldersComboModel::Item::Item(const BookmarkNode* node,
38 Type type)
39 : node(node),
40 type(type) {
43 RecentlyUsedFoldersComboModel::Item::~Item() {}
45 bool RecentlyUsedFoldersComboModel::Item::operator==(const Item& item) const {
46 return item.node == node && item.type == type;
49 RecentlyUsedFoldersComboModel::RecentlyUsedFoldersComboModel(
50 BookmarkModel* model,
51 const BookmarkNode* node)
52 : bookmark_model_(model),
53 node_parent_index_(0) {
54 bookmark_model_->AddObserver(this);
55 // Use + 2 to account for bookmark bar and other node.
56 std::vector<const BookmarkNode*> nodes =
57 bookmark_utils::GetMostRecentlyModifiedFolders(model, kMaxMRUFolders + 2);
59 for (size_t i = 0; i < nodes.size(); ++i)
60 items_.push_back(Item(nodes[i], Item::TYPE_NODE));
62 // We special case the placement of these, so remove them from the list, then
63 // fix up the order.
64 RemoveNode(model->bookmark_bar_node());
65 RemoveNode(model->mobile_node());
66 RemoveNode(model->other_node());
67 RemoveNode(node->parent());
69 // Make the parent the first item, unless it's a permanent node, which is
70 // added below.
71 if (!model->is_permanent_node(node->parent()))
72 items_.insert(items_.begin(), Item(node->parent(), Item::TYPE_NODE));
74 // Make sure we only have kMaxMRUFolders in the first chunk.
75 if (items_.size() > kMaxMRUFolders)
76 items_.erase(items_.begin() + kMaxMRUFolders, items_.end());
78 // And put the bookmark bar and other nodes at the end of the list.
79 items_.push_back(Item(model->bookmark_bar_node(), Item::TYPE_NODE));
80 items_.push_back(Item(model->other_node(), Item::TYPE_NODE));
81 if (model->mobile_node()->IsVisible())
82 items_.push_back(Item(model->mobile_node(), Item::TYPE_NODE));
83 items_.push_back(Item(NULL, Item::TYPE_SEPARATOR));
84 items_.push_back(Item(NULL, Item::TYPE_CHOOSE_ANOTHER_FOLDER));
86 std::vector<Item>::iterator it = std::find(items_.begin(),
87 items_.end(),
88 Item(node->parent(),
89 Item::TYPE_NODE));
90 node_parent_index_ = static_cast<int>(it - items_.begin());
93 RecentlyUsedFoldersComboModel::~RecentlyUsedFoldersComboModel() {
94 bookmark_model_->RemoveObserver(this);
97 int RecentlyUsedFoldersComboModel::GetItemCount() const {
98 return static_cast<int>(items_.size());
101 base::string16 RecentlyUsedFoldersComboModel::GetItemAt(int index) {
102 switch (items_[index].type) {
103 case Item::TYPE_NODE:
104 return items_[index].node->GetTitle();
105 case Item::TYPE_SEPARATOR:
106 // This function should not be called for separators.
107 NOTREACHED();
108 return base::string16();
109 case Item::TYPE_CHOOSE_ANOTHER_FOLDER:
110 return l10n_util::GetStringUTF16(
111 IDS_BOOKMARK_BUBBLE_CHOOSER_ANOTHER_FOLDER);
113 NOTREACHED();
114 return base::string16();
117 bool RecentlyUsedFoldersComboModel::IsItemSeparatorAt(int index) {
118 return items_[index].type == Item::TYPE_SEPARATOR;
121 int RecentlyUsedFoldersComboModel::GetDefaultIndex() const {
122 return node_parent_index_;
125 void RecentlyUsedFoldersComboModel::AddObserver(
126 ui::ComboboxModelObserver* observer) {
127 observers_.AddObserver(observer);
130 void RecentlyUsedFoldersComboModel::RemoveObserver(
131 ui::ComboboxModelObserver* observer) {
132 observers_.RemoveObserver(observer);
135 void RecentlyUsedFoldersComboModel::BookmarkModelLoaded(BookmarkModel* model,
136 bool ids_reassigned) {}
138 void RecentlyUsedFoldersComboModel::BookmarkModelBeingDeleted(
139 BookmarkModel* model) {
142 void RecentlyUsedFoldersComboModel::BookmarkNodeMoved(
143 BookmarkModel* model,
144 const BookmarkNode* old_parent,
145 int old_index,
146 const BookmarkNode* new_parent,
147 int new_index) {
150 void RecentlyUsedFoldersComboModel::BookmarkNodeAdded(
151 BookmarkModel* model,
152 const BookmarkNode* parent,
153 int index) {
156 void RecentlyUsedFoldersComboModel::OnWillRemoveBookmarks(
157 BookmarkModel* model,
158 const BookmarkNode* parent,
159 int old_index,
160 const BookmarkNode* node) {
161 // Changing is rare enough that we don't attempt to readjust the contents.
162 // Update |items_| so we aren't left pointing to a deleted node.
163 bool changed = false;
164 for (std::vector<Item>::iterator i = items_.begin();
165 i != items_.end();) {
166 if (i->type == Item::TYPE_NODE && i->node->HasAncestor(node)) {
167 i = items_.erase(i);
168 changed = true;
169 } else {
170 ++i;
173 if (changed) {
174 FOR_EACH_OBSERVER(ui::ComboboxModelObserver, observers_,
175 OnComboboxModelChanged(this));
179 void RecentlyUsedFoldersComboModel::BookmarkNodeRemoved(
180 BookmarkModel* model,
181 const BookmarkNode* parent,
182 int old_index,
183 const BookmarkNode* node,
184 const std::set<GURL>& removed_urls) {}
186 void RecentlyUsedFoldersComboModel::BookmarkNodeChanged(
187 BookmarkModel* model,
188 const BookmarkNode* node) {
191 void RecentlyUsedFoldersComboModel::BookmarkNodeFaviconChanged(
192 BookmarkModel* model,
193 const BookmarkNode* node) {
196 void RecentlyUsedFoldersComboModel::BookmarkNodeChildrenReordered(
197 BookmarkModel* model,
198 const BookmarkNode* node) {
201 void RecentlyUsedFoldersComboModel::BookmarkAllNodesRemoved(
202 BookmarkModel* model,
203 const std::set<GURL>& removed_urls) {
204 // Changing is rare enough that we don't attempt to readjust the contents.
205 // Update |items_| so we aren't left pointing to a deleted node.
206 bool changed = false;
207 for (std::vector<Item>::iterator i = items_.begin();
208 i != items_.end();) {
209 if (i->type == Item::TYPE_NODE &&
210 !bookmark_model_->is_permanent_node(i->node)) {
211 i = items_.erase(i);
212 changed = true;
213 } else {
214 ++i;
217 if (changed) {
218 FOR_EACH_OBSERVER(ui::ComboboxModelObserver, observers_,
219 OnComboboxModelChanged(this));
223 void RecentlyUsedFoldersComboModel::MaybeChangeParent(
224 const BookmarkNode* node,
225 int selected_index) {
226 if (items_[selected_index].type != Item::TYPE_NODE)
227 return;
229 const BookmarkNode* new_parent = GetNodeAt(selected_index);
230 if (new_parent != node->parent()) {
231 content::RecordAction(
232 base::UserMetricsAction("BookmarkBubble_ChangeParent"));
233 bookmark_model_->Move(node, new_parent, new_parent->child_count());
237 const BookmarkNode* RecentlyUsedFoldersComboModel::GetNodeAt(int index) {
238 if (index < 0 || index >= static_cast<int>(items_.size()))
239 return NULL;
240 return items_[index].node;
243 void RecentlyUsedFoldersComboModel::RemoveNode(const BookmarkNode* node) {
244 std::vector<Item>::iterator it = std::find(items_.begin(),
245 items_.end(),
246 Item(node, Item::TYPE_NODE));
247 if (it != items_.end())
248 items_.erase(it);