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 // BookmarkUndoOperation ------------------------------------------------------ | |
19 | |
20 // Base class for all bookmark related UndoOperations that facilitates access to | |
21 // the BookmarkUndoService. | |
22 class BookmarkUndoOperation : public UndoOperation { | |
23 public: | |
24 explicit BookmarkUndoOperation(Profile* profile); | |
25 virtual ~BookmarkUndoOperation() {} | |
26 | |
27 // If a bookmark node id is renumbered due to an undo operation, the | |
28 // BookmarkUndoOperation should be updated with the new id in order to | |
29 // properly locate the bookmark node during execution of Undo. | |
30 virtual void RenumberBookmarkId(int64 old_id, int64 new_id) = 0; | |
sky
2013/08/06 22:04:07
Wouldn't BookmarkIdChanged be a better name for th
Tom Cassiotis
2013/08/19 13:47:00
I did use the 'verb' and 'event' form of the funct
| |
31 | |
32 BookmarkModel* GetBookmarkModel() const; | |
33 BookmarkUndoService* GetBookmarkUndoService() const; | |
34 | |
35 private: | |
36 Profile* profile_; | |
37 }; | |
38 | |
39 BookmarkUndoOperation::BookmarkUndoOperation(Profile* profile) | |
40 : profile_(profile) { | |
41 } | |
42 | |
43 BookmarkModel* BookmarkUndoOperation::GetBookmarkModel() const { | |
44 return BookmarkModelFactory::GetForProfile(profile_); | |
45 } | |
46 | |
47 BookmarkUndoService* BookmarkUndoOperation::GetBookmarkUndoService() const { | |
48 return BookmarkUndoServiceFactory::GetForProfile(profile_); | |
49 } | |
50 | |
51 // BookmarkAddOperation ------------------------------------------------------- | |
52 | |
53 // Handles the undo of the insertion of a bookmark or folder. | |
54 class BookmarkAddOperation : public BookmarkUndoOperation { | |
55 public: | |
56 BookmarkAddOperation(Profile* profile, const BookmarkNode* parent, int index); | |
57 virtual ~BookmarkAddOperation() {} | |
58 | |
59 // UndoOperation: | |
60 virtual void Undo() OVERRIDE; | |
61 | |
62 // BookmarkUndoOperation: | |
63 virtual void RenumberBookmarkId(int64 old_id, int64 new_id) OVERRIDE; | |
64 | |
65 private: | |
66 int64 parent_id_; | |
67 int index_; | |
68 | |
69 DISALLOW_COPY_AND_ASSIGN(BookmarkAddOperation); | |
70 }; | |
71 | |
72 BookmarkAddOperation::BookmarkAddOperation(Profile* profile, | |
73 const BookmarkNode* parent, | |
74 int index) | |
75 : BookmarkUndoOperation(profile), | |
76 parent_id_(parent->id()), | |
77 index_(index) { | |
78 } | |
79 | |
80 void BookmarkAddOperation::Undo() { | |
81 BookmarkModel* model = GetBookmarkModel(); | |
82 const BookmarkNode* parent = model->GetNodeByID(parent_id_); | |
83 DCHECK(parent); | |
84 | |
85 model->Remove(parent, index_); | |
86 } | |
87 | |
88 void BookmarkAddOperation::RenumberBookmarkId(int64 old_id, int64 new_id) { | |
89 if (parent_id_ == old_id) | |
90 parent_id_ = new_id; | |
91 } | |
92 | |
93 // BookmarkRemoveOperation ---------------------------------------------------- | |
94 | |
95 // Handles the undo of the deletion of a bookmark node. For a bookmark folder, | |
96 // the information for all descendant bookmark nodes is maintained. | |
97 // | |
98 // The BookmarkModel allows only single bookmark node to be removed. | |
99 class BookmarkRemoveOperation : public BookmarkUndoOperation { | |
100 public: | |
101 BookmarkRemoveOperation(Profile* profile, | |
102 const BookmarkNode* parent, | |
103 int old_index, | |
104 const BookmarkNode* node); | |
105 virtual ~BookmarkRemoveOperation() {} | |
106 | |
107 // UndoOperation: | |
108 virtual void Undo() OVERRIDE; | |
109 | |
110 // BookmarkUndoOperation: | |
111 virtual void RenumberBookmarkId(int64 old_id, int64 new_id) OVERRIDE; | |
112 | |
113 private: | |
114 void GetNewBookmarkIds(const BookmarkNodeData::Element& element, | |
sky
2013/08/06 22:04:07
This doesn't actually Get anything. Maybe this sho
Tom Cassiotis
2013/08/19 13:47:00
Done.
| |
115 const BookmarkNode* parent, | |
116 int index_added_at) const; | |
117 | |
118 int64 parent_id_; | |
119 int old_index_; | |
sky
2013/08/06 22:04:07
const?
Tom Cassiotis
2013/08/19 13:47:00
Done.
| |
120 BookmarkNodeData removed_node_; | |
121 | |
122 DISALLOW_COPY_AND_ASSIGN(BookmarkRemoveOperation); | |
123 }; | |
124 | |
125 BookmarkRemoveOperation::BookmarkRemoveOperation(Profile* profile, | |
126 const BookmarkNode* parent, | |
127 int old_index, | |
128 const BookmarkNode* node) | |
129 : BookmarkUndoOperation(profile), | |
130 parent_id_(parent->id()), | |
131 old_index_(old_index), | |
132 removed_node_(node) { | |
133 } | |
134 | |
135 void BookmarkRemoveOperation::Undo() { | |
136 DCHECK(removed_node_.is_valid()); | |
137 BookmarkModel* model = GetBookmarkModel(); | |
138 const BookmarkNode* parent = model->GetNodeByID(parent_id_); | |
139 DCHECK(parent); | |
140 | |
141 bookmark_utils::CloneBookmarkNode(model, | |
sky
2013/08/06 22:04:07
One thing I'm not sure about is meta info. Do we n
Tom Cassiotis
2013/08/19 13:47:00
Currently the only use for the meta info is for ve
| |
142 removed_node_.elements, | |
143 parent, | |
144 old_index_); | |
145 GetNewBookmarkIds(removed_node_.elements[0], parent, old_index_); | |
146 } | |
147 | |
148 void BookmarkRemoveOperation::GetNewBookmarkIds( | |
149 const BookmarkNodeData::Element& element, | |
150 const BookmarkNode* parent, | |
151 int index_added_at) const { | |
152 BookmarkModel* model = GetBookmarkModel(); | |
153 BookmarkUndoService* undo_service = GetBookmarkUndoService(); | |
154 | |
155 const BookmarkNode* node = parent->GetChild(index_added_at); | |
156 if (element.id() != node->id()) | |
157 undo_service->OnBookmarkRenumbered(element.id(), node->id()); | |
158 | |
159 if (!element.is_url) { | |
160 for (int i = 0; i < static_cast<int>(element.children.size()); ++i) | |
161 GetNewBookmarkIds(element.children[i], node, 0); | |
162 } | |
163 } | |
164 | |
165 void BookmarkRemoveOperation::RenumberBookmarkId(int64 old_id, int64 new_id) { | |
166 if (parent_id_ == old_id) | |
167 parent_id_ = new_id; | |
168 } | |
169 | |
170 // BookmarkEditOperation ------------------------------------------------------ | |
171 | |
172 // Handles the undo of the modification of a bookmark node. | |
173 class BookmarkEditOperation : public BookmarkUndoOperation { | |
174 public: | |
175 BookmarkEditOperation(Profile* profile, | |
176 const BookmarkNode* node); | |
177 virtual ~BookmarkEditOperation() {} | |
178 | |
179 // UndoOperation: | |
180 virtual void Undo() OVERRIDE; | |
181 | |
182 // BookmarkUndoOperation: | |
183 virtual void RenumberBookmarkId(int64 old_id, int64 new_id) OVERRIDE; | |
184 | |
185 private: | |
186 int64 node_id_; | |
187 BookmarkNodeData original_bookmark_; | |
188 | |
189 DISALLOW_COPY_AND_ASSIGN(BookmarkEditOperation); | |
190 }; | |
191 | |
192 BookmarkEditOperation::BookmarkEditOperation(Profile* profile, | |
193 const BookmarkNode* node) | |
194 : BookmarkUndoOperation(profile), | |
195 node_id_(node->id()), | |
196 original_bookmark_(node) { | |
197 } | |
198 | |
199 void BookmarkEditOperation::Undo() { | |
200 DCHECK(original_bookmark_.is_valid()); | |
201 BookmarkModel* model = GetBookmarkModel(); | |
202 const BookmarkNode* node = model->GetNodeByID(node_id_); | |
203 DCHECK(node); | |
204 | |
205 model->SetTitle(node, original_bookmark_.elements[0].title); | |
206 if (original_bookmark_.elements[0].is_url) | |
sky
2013/08/06 22:04:07
Should this reset last modified too?
Tom Cassiotis
2013/08/19 13:47:00
Did you mean date_folder_modified_?
If that prope
sky
2013/08/19 15:38:00
We don't want pasting to restore dates, only undo.
Tom Cassiotis
2013/08/27 14:39:29
Done.
| |
207 model->SetURL(node, original_bookmark_.elements[0].url); | |
208 } | |
209 | |
210 void BookmarkEditOperation::RenumberBookmarkId(int64 old_id, int64 new_id) { | |
211 if (node_id_ == old_id) | |
212 node_id_ = new_id; | |
213 } | |
214 | |
215 // BookmarkMoveOperation ------------------------------------------------------ | |
216 | |
217 // Handles the undo of a bookmark being moved to a new location. | |
218 class BookmarkMoveOperation : public BookmarkUndoOperation { | |
219 public: | |
220 BookmarkMoveOperation(Profile* profile, | |
221 const BookmarkNode* old_parent, | |
222 int old_index, | |
223 const BookmarkNode* new_parent, | |
224 int new_index); | |
225 virtual ~BookmarkMoveOperation() {} | |
226 | |
227 // UndoOperation: | |
228 virtual void Undo() OVERRIDE; | |
229 | |
230 // BookmarkUndoOperation: | |
231 virtual void RenumberBookmarkId(int64 old_id, int64 new_id) OVERRIDE; | |
232 | |
233 private: | |
234 int64 old_parent_id_; | |
235 int64 new_parent_id_; | |
236 int old_index_; | |
237 int new_index_; | |
238 | |
239 DISALLOW_COPY_AND_ASSIGN(BookmarkMoveOperation); | |
240 }; | |
241 | |
242 BookmarkMoveOperation::BookmarkMoveOperation(Profile* profile, | |
243 const BookmarkNode* old_parent, | |
244 int old_index, | |
245 const BookmarkNode* new_parent, | |
246 int new_index) | |
247 : BookmarkUndoOperation(profile), | |
248 old_parent_id_(old_parent->id()), | |
249 old_index_(old_index), | |
250 new_parent_id_(new_parent->id()), | |
251 new_index_(new_index) { | |
252 } | |
253 | |
254 void BookmarkMoveOperation::Undo() { | |
255 BookmarkModel* model = GetBookmarkModel(); | |
256 const BookmarkNode* old_parent = model->GetNodeByID(old_parent_id_); | |
257 const BookmarkNode* new_parent = model->GetNodeByID(new_parent_id_); | |
258 DCHECK(old_parent); | |
259 DCHECK(new_parent); | |
260 | |
261 const BookmarkNode* node = new_parent->GetChild(new_index_); | |
262 int destination_index = old_index_; | |
263 | |
264 // If the bookmark was moved up within the same parent then the destination | |
265 // index needs to be incremented since the old index did not account for the | |
266 // moved bookmark. | |
267 if (old_parent == new_parent && new_index_ < old_index_) | |
268 ++destination_index; | |
269 | |
270 model->Move(node, old_parent, destination_index); | |
271 } | |
272 | |
273 void BookmarkMoveOperation::RenumberBookmarkId(int64 old_id, int64 new_id) { | |
274 if (old_parent_id_ == old_id) | |
275 old_parent_id_ = new_id; | |
276 if (new_parent_id_ == old_id) | |
277 new_parent_id_ = new_id; | |
278 } | |
279 | |
280 // BookmarkReorderOperation --------------------------------------------------- | |
281 | |
282 // Handle the undo of reordering of bookmarks that can happen as a result of | |
283 // sorting a bookmark folder by name or the undo of that operation. The change | |
284 // of order is not recursive so only the order of the immediate children of the | |
285 // folder need to be restored. | |
286 class BookmarkReorderOperation : public BookmarkUndoOperation { | |
287 public: | |
288 BookmarkReorderOperation(Profile* profile, | |
289 const BookmarkNode* parent); | |
290 virtual ~BookmarkReorderOperation(); | |
291 | |
292 // UndoOperation: | |
293 virtual void Undo() OVERRIDE; | |
294 | |
295 // BookmarkUndoOperation: | |
296 virtual void RenumberBookmarkId(int64 old_id, int64 new_id) OVERRIDE; | |
297 | |
298 private: | |
299 int64 parent_id_; | |
300 std::vector<int64> ordered_bookmarks_; | |
301 | |
302 DISALLOW_COPY_AND_ASSIGN(BookmarkReorderOperation); | |
303 }; | |
304 | |
305 BookmarkReorderOperation::BookmarkReorderOperation(Profile* profile, | |
306 const BookmarkNode* parent) | |
307 : BookmarkUndoOperation(profile), | |
308 parent_id_(parent->id()) { | |
309 ordered_bookmarks_.resize(parent->child_count()); | |
310 for (int i = 0; i < parent->child_count(); ++i) | |
311 ordered_bookmarks_[i] = parent->GetChild(i)->id(); | |
312 } | |
313 | |
314 BookmarkReorderOperation::~BookmarkReorderOperation() { | |
315 } | |
316 | |
317 void BookmarkReorderOperation::Undo() { | |
318 BookmarkModel* model = GetBookmarkModel(); | |
319 const BookmarkNode* parent = model->GetNodeByID(parent_id_); | |
320 DCHECK(parent); | |
321 | |
322 std::vector<const BookmarkNode*> ordered_nodes; | |
323 for (size_t i = 0; i < ordered_bookmarks_.size(); ++i) | |
324 ordered_nodes.push_back(model->GetNodeByID(ordered_bookmarks_[i])); | |
325 | |
326 model->ReorderChildren(parent, ordered_nodes); | |
327 } | |
328 | |
329 void BookmarkReorderOperation::RenumberBookmarkId(int64 old_id, int64 new_id) { | |
330 if (parent_id_ == old_id) | |
sky
2013/08/06 22:04:07
Doesn't this need to check ordered_bookmarks_ ?
Tom Cassiotis
2013/08/19 13:47:00
Done.
| |
331 parent_id_ = new_id; | |
332 } | |
333 | |
334 } // namespace | |
335 | |
336 // BookmarkUndoService -------------------------------------------------------- | |
337 | |
338 BookmarkUndoService::BookmarkUndoService(Profile* profile) : profile_(profile) { | |
339 BookmarkModelFactory::GetForProfile(profile_)->AddObserver(this); | |
340 } | |
341 | |
342 BookmarkUndoService::~BookmarkUndoService() { | |
343 BookmarkModelFactory::GetForProfile(profile_)->RemoveObserver(this); | |
344 } | |
345 | |
346 void BookmarkUndoService::OnBookmarkRenumbered(int64 old_id, int64 new_id) { | |
347 std::vector<UndoOperation*> all_operations = | |
348 undo_manager()->GetAllUndoOperations(); | |
349 for (std::vector<UndoOperation*>::iterator it = all_operations.begin(); | |
350 it != all_operations.end(); ++it) { | |
351 static_cast<BookmarkUndoOperation*>(*it)->RenumberBookmarkId(old_id, | |
352 new_id); | |
353 } | |
354 } | |
355 | |
356 void BookmarkUndoService::Loaded(BookmarkModel* model, bool ids_reassigned) { | |
357 undo_manager_.RemoveAllOperations(); | |
358 } | |
359 | |
360 void BookmarkUndoService::BookmarkModelBeingDeleted(BookmarkModel* model) { | |
361 undo_manager_.RemoveAllOperations(); | |
362 } | |
363 | |
364 void BookmarkUndoService::BookmarkNodeMoved(BookmarkModel* model, | |
365 const BookmarkNode* old_parent, | |
366 int old_index, | |
367 const BookmarkNode* new_parent, | |
368 int new_index) { | |
369 scoped_ptr<UndoOperation> op(new BookmarkMoveOperation(profile_, | |
370 old_parent, | |
371 old_index, | |
372 new_parent, | |
373 new_index)); | |
374 undo_manager()->AddUndoOperation(op.Pass()); | |
375 } | |
376 | |
377 void BookmarkUndoService::BookmarkNodeAdded(BookmarkModel* model, | |
378 const BookmarkNode* parent, | |
379 int index) { | |
380 scoped_ptr<UndoOperation> op(new BookmarkAddOperation(profile_, | |
381 parent, | |
382 index)); | |
383 undo_manager()->AddUndoOperation(op.Pass()); | |
384 } | |
385 | |
386 void BookmarkUndoService::OnWillRemoveBookmarks(BookmarkModel* model, | |
387 const BookmarkNode* parent, | |
388 int old_index, | |
389 const BookmarkNode* node) { | |
390 scoped_ptr<UndoOperation> op(new BookmarkRemoveOperation(profile_, | |
391 parent, | |
392 old_index, | |
393 node)); | |
394 undo_manager()->AddUndoOperation(op.Pass()); | |
395 } | |
396 | |
397 void BookmarkUndoService::OnWillRemoveAllBookmarks(BookmarkModel* model) { | |
398 ScopedGroupingAction merge_removes(undo_manager()); | |
399 for (int i = 0; i < model->root_node()->child_count(); ++i) { | |
400 const BookmarkNode* permanent_node = model->root_node()->GetChild(i); | |
401 for (int j = permanent_node->child_count() - 1; j >= 0; --j) { | |
402 scoped_ptr<UndoOperation> op(new BookmarkRemoveOperation(profile_, | |
403 permanent_node, j, permanent_node->GetChild(j))); | |
404 undo_manager()->AddUndoOperation(op.Pass()); | |
405 } | |
406 } | |
407 } | |
408 | |
409 void BookmarkUndoService::OnWillChangeBookmarkNode(BookmarkModel* model, | |
410 const BookmarkNode* node) { | |
411 scoped_ptr<UndoOperation> op(new BookmarkEditOperation(profile_, node)); | |
412 undo_manager()->AddUndoOperation(op.Pass()); | |
413 } | |
414 | |
415 void BookmarkUndoService::OnWillReorderBookmarkNode(BookmarkModel* model, | |
416 const BookmarkNode* node) { | |
417 scoped_ptr<UndoOperation> op(new BookmarkReorderOperation(profile_, node)); | |
418 undo_manager()->AddUndoOperation(op.Pass()); | |
419 } | |
OLD | NEW |