OLD | NEW |
---|---|
(Empty) | |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 #include "chrome/browser/undo/bookmark_undo_service.h" | |
6 | |
7 #include "chrome/browser/bookmarks/bookmark_model.h" | |
8 #include "chrome/browser/bookmarks/bookmark_model_factory.h" | |
9 #include "chrome/browser/bookmarks/bookmark_node_data.h" | |
10 #include "chrome/browser/bookmarks/bookmark_utils.h" | |
11 #include "chrome/browser/profiles/profile.h" | |
12 #include "chrome/browser/undo/bookmark_undo_service_factory.h" | |
13 #include "chrome/browser/undo/undo_manager_utils.h" | |
14 #include "chrome/browser/undo/undo_operation.h" | |
15 | |
16 namespace { | |
17 | |
18 // Helper to get a mutable bookmark node. | |
19 BookmarkNode* AsMutable(const BookmarkNode* node) { | |
sky
2013/07/18 14:35:41
There should be no reason for this. If there is, i
Tom Cassiotis
2013/07/24 15:37:56
AsMutable is used in one place to reorder the chil
sky
2013/07/26 15:29:51
I think BookmarkModel::ReorderChildren should take
| |
20 return const_cast<BookmarkNode*>(node); | |
21 } | |
22 | |
23 // BookmarkUndoOperation ------------------------------------------------------ | |
24 | |
25 // Base class for all bookmark related UndoOperations that facilitates access to | |
26 // the BookmarkUndoService. | |
27 class BookmarkUndoOperation : public UndoOperation { | |
sky
2013/07/18 14:35:41
The style guide indicates you should separate decl
Tom Cassiotis
2013/07/24 15:37:56
Done.
| |
28 public: | |
29 explicit BookmarkUndoOperation(BookmarkUndoService* bookmark_undo) | |
30 : bookmark_undo_(bookmark_undo) { | |
31 } | |
32 virtual ~BookmarkUndoOperation() {} | |
33 | |
34 BookmarkModel* GetBookmarkModel() { | |
35 return bookmark_undo_->GetBookmarkModel(); | |
36 } | |
37 BookmarkIdMap* GetBookmarkIdMap() { | |
38 return &bookmark_undo_->bookmark_id_map_; | |
39 } | |
40 private: | |
41 BookmarkUndoService* bookmark_undo_; | |
42 }; | |
sky
2013/07/18 14:35:41
DISALLOW... and newline between 39/40
Tom Cassiotis
2013/07/24 15:37:56
The reason I did not include a the DISALLOW_ line
| |
43 | |
44 // BookmarkAddOperation ------------------------------------------------------- | |
45 | |
46 // Handles the undo of the insertion of a bookmark or folder. | |
47 class BookmarkAddOperation : public BookmarkUndoOperation { | |
48 public: | |
49 BookmarkAddOperation(BookmarkUndoService* bookmark_undo, | |
50 const BookmarkNode* parent, | |
51 int index); | |
52 virtual ~BookmarkAddOperation() {} | |
53 | |
54 virtual void Undo() OVERRIDE; | |
55 | |
56 private: | |
57 int64 parent_id_; | |
sky
2013/07/18 14:35:41
Use const where you can in all these classes.
Tom Cassiotis
2013/07/24 15:37:56
I have not seen any parameters or functions that I
| |
58 int index_; | |
59 | |
60 DISALLOW_COPY_AND_ASSIGN(BookmarkAddOperation); | |
61 }; | |
62 | |
63 BookmarkAddOperation::BookmarkAddOperation(BookmarkUndoService* bookmark_undo, | |
64 const BookmarkNode* parent, | |
65 int index) | |
66 : BookmarkUndoOperation(bookmark_undo), | |
67 parent_id_(parent->id()), | |
68 index_(index) { | |
69 } | |
70 | |
71 void BookmarkAddOperation::Undo() { | |
72 BookmarkModel* model = GetBookmarkModel(); | |
73 BookmarkIdMap* id_map = GetBookmarkIdMap(); | |
74 const BookmarkNode* parent = | |
75 model->GetNodeByID(id_map->GetCurrentId(parent_id_)); | |
76 DCHECK(parent); | |
77 | |
78 model->Remove(parent, index_); | |
79 } | |
80 | |
81 // BookmarkRemoveOperation ---------------------------------------------------- | |
82 | |
83 // Handles the undo of the deletion of a bookmark node. For a bookmark folder, | |
84 // the information for all descendant bookmark nodes is maintained. | |
85 // | |
86 // The BookmarkModel allows only single bookmark node to be removed. | |
87 class BookmarkRemoveOperation : public BookmarkUndoOperation { | |
88 public: | |
89 BookmarkRemoveOperation(BookmarkUndoService* undo, | |
90 const BookmarkNode* parent, | |
91 int old_index, | |
92 const BookmarkNode* node); | |
93 virtual ~BookmarkRemoveOperation() {} | |
94 | |
95 virtual void Undo() OVERRIDE; | |
96 | |
97 private: | |
98 int64 parent_id_; | |
99 int old_index_; | |
100 BookmarkNodeData removed_node_; | |
101 | |
102 DISALLOW_COPY_AND_ASSIGN(BookmarkRemoveOperation); | |
103 }; | |
104 | |
105 BookmarkRemoveOperation::BookmarkRemoveOperation(BookmarkUndoService* undo, | |
106 const BookmarkNode* parent, | |
107 int old_index, | |
108 const BookmarkNode* node) | |
109 : BookmarkUndoOperation(undo), | |
110 parent_id_(parent->id()), | |
111 old_index_(old_index), | |
112 removed_node_(node) { | |
113 } | |
114 | |
115 void BookmarkRemoveOperation::Undo() { | |
116 DCHECK(removed_node_.is_valid()); | |
117 BookmarkModel* model = GetBookmarkModel(); | |
118 BookmarkIdMap* id_map = GetBookmarkIdMap(); | |
119 const BookmarkNode* parent = | |
120 model->GetNodeByID(id_map->GetCurrentId(parent_id_)); | |
121 DCHECK(parent); | |
122 | |
123 bookmark_utils::CloneBookmarkNode(model, | |
124 removed_node_.elements, | |
125 parent, | |
126 old_index_); | |
127 id_map->ExtractMappings(model, removed_node_.elements[0], parent, old_index_); | |
128 } | |
129 | |
130 // BookmarkEditOperation ------------------------------------------------------ | |
131 | |
132 // Handles the undo of the modification of a bookmark node. | |
133 class BookmarkEditOperation : public BookmarkUndoOperation { | |
134 public: | |
135 BookmarkEditOperation(BookmarkUndoService* bookmark_undo, | |
136 const BookmarkNode* node); | |
137 virtual ~BookmarkEditOperation() {} | |
138 | |
139 virtual void Undo() OVERRIDE; | |
140 | |
141 private: | |
142 int64 nodeId_; | |
143 BookmarkNodeData original_bookmark_; | |
144 | |
145 DISALLOW_COPY_AND_ASSIGN(BookmarkEditOperation); | |
146 }; | |
147 | |
148 BookmarkEditOperation::BookmarkEditOperation(BookmarkUndoService* bookmark_undo, | |
149 const BookmarkNode* node) | |
150 : BookmarkUndoOperation(bookmark_undo), | |
151 nodeId_(node->id()), | |
152 original_bookmark_(node) { | |
153 } | |
154 | |
155 void BookmarkEditOperation::Undo() { | |
156 DCHECK(original_bookmark_.is_valid()); | |
157 BookmarkModel* model = GetBookmarkModel(); | |
158 BookmarkIdMap* id_map = GetBookmarkIdMap(); | |
159 const BookmarkNode* node = model->GetNodeByID(id_map->GetCurrentId(nodeId_)); | |
160 DCHECK(node); | |
161 | |
162 model->SetTitle(node, original_bookmark_.elements[0].title); | |
163 if (original_bookmark_.elements[0].is_url) | |
164 model->SetURL(node, original_bookmark_.elements[0].url); | |
165 } | |
166 | |
167 // BookmarkMoveOperation ------------------------------------------------------ | |
168 | |
169 // Handles the undo of a bookmark being moved to a new location. | |
170 class BookmarkMoveOperation : public BookmarkUndoOperation { | |
171 public: | |
172 BookmarkMoveOperation(BookmarkUndoService* bookmark_undo, | |
173 const BookmarkNode* old_parent, | |
174 int old_index, | |
175 const BookmarkNode* new_parent, | |
176 int new_index); | |
177 virtual ~BookmarkMoveOperation() {} | |
178 | |
179 virtual void Undo() OVERRIDE; | |
180 | |
181 private: | |
182 int64 old_parent_id_; | |
183 int64 new_parent_id_; | |
184 int old_index_; | |
185 int new_index_; | |
186 | |
187 DISALLOW_COPY_AND_ASSIGN(BookmarkMoveOperation); | |
188 }; | |
189 | |
190 BookmarkMoveOperation::BookmarkMoveOperation(BookmarkUndoService* bookmark_undo, | |
191 const BookmarkNode* old_parent, | |
192 int old_index, | |
193 const BookmarkNode* new_parent, | |
194 int new_index) | |
195 : BookmarkUndoOperation(bookmark_undo), | |
196 old_parent_id_(old_parent->id()), | |
197 old_index_(old_index), | |
198 new_parent_id_(new_parent->id()), | |
199 new_index_(new_index) { | |
200 } | |
201 | |
202 void BookmarkMoveOperation::Undo() { | |
203 BookmarkModel* model = GetBookmarkModel(); | |
204 BookmarkIdMap* id_map = GetBookmarkIdMap(); | |
205 const BookmarkNode* old_parent = | |
206 model->GetNodeByID(id_map->GetCurrentId(old_parent_id_)); | |
207 const BookmarkNode* new_parent = | |
208 model->GetNodeByID(id_map->GetCurrentId(new_parent_id_)); | |
209 DCHECK(old_parent); | |
210 DCHECK(new_parent); | |
211 | |
212 const BookmarkNode* node = new_parent->GetChild(new_index_); | |
213 int destination_index = old_index_; | |
214 | |
215 // If the bookmark was moved up within the same parent then the destination | |
216 // index needs to be incremented since the old index did not account for the | |
217 // moved bookmark. | |
218 if (old_parent == new_parent && new_index_ < old_index_) | |
219 ++destination_index; | |
220 | |
221 model->Move(node, old_parent, destination_index); | |
222 } | |
223 | |
224 // BookmarkReorderOperation --------------------------------------------------- | |
225 | |
226 // Handle the undo of reordering of bookmarks that can happen as a result of | |
227 // sorting a bookmark folder by name or the undo of that operation. The change | |
228 // of order is not recursive so only the order of the immediate children of the | |
229 // folder need to be restored. | |
230 class BookmarkReorderOperation : public BookmarkUndoOperation { | |
231 public: | |
232 BookmarkReorderOperation(BookmarkUndoService* bookmark_undo, | |
233 const BookmarkNode* parent); | |
234 virtual ~BookmarkReorderOperation(); | |
235 | |
236 virtual void Undo() OVERRIDE; | |
237 | |
238 private: | |
239 int64 parent_id_; | |
240 std::vector<int64> ordered_bookmarks_; | |
241 | |
242 DISALLOW_COPY_AND_ASSIGN(BookmarkReorderOperation); | |
243 }; | |
244 | |
245 BookmarkReorderOperation::BookmarkReorderOperation(BookmarkUndoService* undo, | |
246 const BookmarkNode* parent) | |
247 : BookmarkUndoOperation(undo), | |
248 parent_id_(parent->id()) { | |
249 ordered_bookmarks_.resize(parent->child_count()); | |
250 for (int i = 0; i < parent->child_count(); ++i) | |
251 ordered_bookmarks_[i] = parent->GetChild(i)->id(); | |
252 } | |
253 | |
254 BookmarkReorderOperation::~BookmarkReorderOperation() { | |
255 } | |
256 | |
257 void BookmarkReorderOperation::Undo() { | |
258 BookmarkModel* model = GetBookmarkModel(); | |
259 BookmarkIdMap* id_map = GetBookmarkIdMap(); | |
260 const BookmarkNode* parent = | |
261 model->GetNodeByID(id_map->GetCurrentId(parent_id_)); | |
262 DCHECK(parent); | |
263 | |
264 std::vector<BookmarkNode*> ordered_nodes; | |
265 for (size_t i = 0; i < ordered_bookmarks_.size(); ++i) { | |
266 const BookmarkNode* node = | |
267 model->GetNodeByID(id_map->GetCurrentId(ordered_bookmarks_[i])); | |
268 ordered_nodes.push_back(AsMutable(node)); | |
269 } | |
270 | |
271 model->ReorderChildren(parent, ordered_nodes); | |
272 } | |
273 | |
274 } // namespace | |
275 | |
276 // BookmarkIdMap -------------------------------------------------------------- | |
277 | |
278 BookmarkIdMap::BookmarkIdMap() { | |
279 } | |
280 | |
281 BookmarkIdMap::~BookmarkIdMap() { | |
282 } | |
283 | |
284 int64 BookmarkIdMap::GetCurrentId(int64 oldIndex) { | |
285 int64 currentIndex = oldIndex; | |
286 | |
287 std::map<int64, int64>::const_iterator it; | |
288 while ((it = identifier_map_.find(currentIndex)) != identifier_map_.end()) | |
289 currentIndex = it->second; | |
290 return currentIndex; | |
291 } | |
292 | |
293 void BookmarkIdMap::AddMapping(int64 old_index, int64 new_index) { | |
294 identifier_map_[old_index] = new_index; | |
295 } | |
296 | |
297 void BookmarkIdMap::ExtractMappings(BookmarkModel* model, | |
298 const BookmarkNodeData::Element& element, | |
299 const BookmarkNode* parent, | |
300 int index_added_at) { | |
301 const BookmarkNode* node = parent->GetChild(index_added_at); | |
302 if (element.id() != node->id()) | |
303 AddMapping(element.id(), node->id()); | |
304 if (!element.is_url) { | |
305 for (int i = 0; i < static_cast<int>(element.children.size()); ++i) | |
306 ExtractMappings(model, element.children[i], node, 0); | |
307 } | |
308 } | |
309 | |
310 // BookmarkUndoService -------------------------------------------------------- | |
311 | |
312 BookmarkUndoService::BookmarkUndoService(Profile* profile) | |
313 : profile_(profile), | |
314 model_(NULL) { | |
315 BookmarkModelFactory::GetForProfile(profile_)->AddObserver(this); | |
316 } | |
317 | |
318 BookmarkUndoService::BookmarkUndoService(BookmarkModel* model) | |
319 : profile_(NULL), | |
320 model_(model) { | |
321 model_->AddObserver(this); | |
322 } | |
323 | |
324 BookmarkUndoService::~BookmarkUndoService() { | |
325 GetBookmarkModel()->RemoveObserver(this); | |
326 } | |
327 | |
328 BookmarkModel* BookmarkUndoService::GetBookmarkModel() { | |
329 return profile_ ? BookmarkModelFactory::GetForProfile(profile_) : model_; | |
330 } | |
331 | |
332 void BookmarkUndoService::Loaded(BookmarkModel* model, bool ids_reassigned) { | |
333 undo_manager_.Reset(); | |
334 } | |
335 | |
336 void BookmarkUndoService::BookmarkModelBeingDeleted(BookmarkModel* model) { | |
337 undo_manager_.Reset(); | |
338 } | |
339 | |
340 void BookmarkUndoService::BookmarkNodeMoved(BookmarkModel* model, | |
341 const BookmarkNode* old_parent, | |
342 int old_index, | |
343 const BookmarkNode* new_parent, | |
344 int new_index) { | |
345 scoped_ptr<UndoOperation> op(new BookmarkMoveOperation(this, | |
346 old_parent, | |
347 old_index, | |
348 new_parent, | |
349 new_index)); | |
350 GetUndoManager()->AddUndoOperation(op.Pass()); | |
351 } | |
352 | |
353 void BookmarkUndoService::BookmarkNodeAdded(BookmarkModel* model, | |
354 const BookmarkNode* parent, | |
355 int index) { | |
356 scoped_ptr<UndoOperation> op(new BookmarkAddOperation(this, parent, index)); | |
357 GetUndoManager()->AddUndoOperation(op.Pass()); | |
358 } | |
359 | |
360 void BookmarkUndoService::OnWillRemoveBookmarks(BookmarkModel* model, | |
361 const BookmarkNode* parent, | |
362 int old_index, | |
363 const BookmarkNode* node) { | |
364 scoped_ptr<UndoOperation> op(new BookmarkRemoveOperation(this, | |
365 parent, | |
366 old_index, | |
367 node)); | |
368 GetUndoManager()->AddUndoOperation(op.Pass()); | |
369 } | |
370 | |
371 void BookmarkUndoService::OnWillRemoveAllBookmarks(BookmarkModel* model) { | |
372 ScopedGroupingAction merge_removes(GetUndoManager()); | |
373 for (int i = 0; i < model->root_node()->child_count(); ++i) { | |
374 const BookmarkNode* permanent_node = model->root_node()->GetChild(i); | |
375 for (int j = permanent_node->child_count() - 1; j >= 0; --j) { | |
376 scoped_ptr<UndoOperation> op(new BookmarkRemoveOperation(this, | |
377 permanent_node, j, permanent_node->GetChild(j))); | |
378 GetUndoManager()->AddUndoOperation(op.Pass()); | |
379 } | |
380 } | |
381 } | |
382 | |
383 | |
384 void BookmarkUndoService::OnWillChangeBookmarkNode(BookmarkModel* model, | |
385 const BookmarkNode* node) { | |
386 scoped_ptr<UndoOperation> op(new BookmarkEditOperation(this, node)); | |
387 GetUndoManager()->AddUndoOperation(op.Pass()); | |
388 } | |
389 | |
390 void BookmarkUndoService::OnWillReorderBookmarkNode(BookmarkModel* model, | |
391 const BookmarkNode* node) { | |
392 scoped_ptr<UndoOperation> op(new BookmarkReorderOperation(this, node)); | |
393 GetUndoManager()->AddUndoOperation(op.Pass()); | |
394 } | |
OLD | NEW |