Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(19)

Side by Side Diff: chrome/browser/undo/bookmark_undo_service.cc

Issue 19287013: Bookmark Undo service for multiple level undo/redo of bookmarks. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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;
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 const 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 UpdateBookmarkIds(const BookmarkNodeData::Element& element,
115 const BookmarkNode* parent,
116 int index_added_at) const;
117
118 int64 parent_id_;
119 const int old_index_;
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, removed_node_.elements, parent,
142 old_index_, false);
143 UpdateBookmarkIds(removed_node_.elements[0], parent, old_index_);
144 }
145
146 void BookmarkRemoveOperation::UpdateBookmarkIds(
147 const BookmarkNodeData::Element& element,
148 const BookmarkNode* parent,
149 int index_added_at) const {
150 BookmarkModel* model = GetBookmarkModel();
151 BookmarkUndoService* undo_service = GetBookmarkUndoService();
152
153 const BookmarkNode* node = parent->GetChild(index_added_at);
154 if (element.id() != node->id())
155 undo_service->OnBookmarkRenumbered(element.id(), node->id());
156
157 if (!element.is_url) {
158 for (int i = 0; i < static_cast<int>(element.children.size()); ++i)
159 UpdateBookmarkIds(element.children[i], node, 0);
160 }
161 }
162
163 void BookmarkRemoveOperation::RenumberBookmarkId(int64 old_id, int64 new_id) {
164 if (parent_id_ == old_id)
165 parent_id_ = new_id;
166 }
167
168 // BookmarkEditOperation ------------------------------------------------------
169
170 // Handles the undo of the modification of a bookmark node.
171 class BookmarkEditOperation : public BookmarkUndoOperation {
172 public:
173 BookmarkEditOperation(Profile* profile,
174 const BookmarkNode* node);
175 virtual ~BookmarkEditOperation() {}
176
177 // UndoOperation:
178 virtual void Undo() OVERRIDE;
179
180 // BookmarkUndoOperation:
181 virtual void RenumberBookmarkId(int64 old_id, int64 new_id) OVERRIDE;
182
183 private:
184 int64 node_id_;
185 BookmarkNodeData original_bookmark_;
186
187 DISALLOW_COPY_AND_ASSIGN(BookmarkEditOperation);
188 };
189
190 BookmarkEditOperation::BookmarkEditOperation(Profile* profile,
191 const BookmarkNode* node)
192 : BookmarkUndoOperation(profile),
193 node_id_(node->id()),
194 original_bookmark_(node) {
195 }
196
197 void BookmarkEditOperation::Undo() {
198 DCHECK(original_bookmark_.is_valid());
199 BookmarkModel* model = GetBookmarkModel();
200 const BookmarkNode* node = model->GetNodeByID(node_id_);
201 DCHECK(node);
202
203 model->SetTitle(node, original_bookmark_.elements[0].title);
204 if (original_bookmark_.elements[0].is_url)
205 model->SetURL(node, original_bookmark_.elements[0].url);
sky 2013/08/27 22:24:18 nit: spacing is off.
Tom Cassiotis 2013/09/04 13:44:43 Done.
206 }
207
208 void BookmarkEditOperation::RenumberBookmarkId(int64 old_id, int64 new_id) {
209 if (node_id_ == old_id)
210 node_id_ = new_id;
211 }
212
213 // BookmarkMoveOperation ------------------------------------------------------
214
215 // Handles the undo of a bookmark being moved to a new location.
216 class BookmarkMoveOperation : public BookmarkUndoOperation {
217 public:
218 BookmarkMoveOperation(Profile* profile,
219 const BookmarkNode* old_parent,
220 int old_index,
221 const BookmarkNode* new_parent,
222 int new_index);
223 virtual ~BookmarkMoveOperation() {}
224
225 // UndoOperation:
226 virtual void Undo() OVERRIDE;
227
228 // BookmarkUndoOperation:
229 virtual void RenumberBookmarkId(int64 old_id, int64 new_id) OVERRIDE;
230
231 private:
232 int64 old_parent_id_;
233 int64 new_parent_id_;
234 int old_index_;
235 int new_index_;
236
237 DISALLOW_COPY_AND_ASSIGN(BookmarkMoveOperation);
238 };
239
240 BookmarkMoveOperation::BookmarkMoveOperation(Profile* profile,
241 const BookmarkNode* old_parent,
242 int old_index,
243 const BookmarkNode* new_parent,
244 int new_index)
245 : BookmarkUndoOperation(profile),
246 old_parent_id_(old_parent->id()),
247 old_index_(old_index),
248 new_parent_id_(new_parent->id()),
249 new_index_(new_index) {
250 }
251
252 void BookmarkMoveOperation::Undo() {
253 BookmarkModel* model = GetBookmarkModel();
254 const BookmarkNode* old_parent = model->GetNodeByID(old_parent_id_);
255 const BookmarkNode* new_parent = model->GetNodeByID(new_parent_id_);
256 DCHECK(old_parent);
257 DCHECK(new_parent);
258
259 const BookmarkNode* node = new_parent->GetChild(new_index_);
260 int destination_index = old_index_;
261
262 // If the bookmark was moved up within the same parent then the destination
263 // index needs to be incremented since the old index did not account for the
264 // moved bookmark.
265 if (old_parent == new_parent && new_index_ < old_index_)
266 ++destination_index;
267
268 model->Move(node, old_parent, destination_index);
269 }
270
271 void BookmarkMoveOperation::RenumberBookmarkId(int64 old_id, int64 new_id) {
272 if (old_parent_id_ == old_id)
273 old_parent_id_ = new_id;
274 if (new_parent_id_ == old_id)
275 new_parent_id_ = new_id;
276 }
277
278 // BookmarkReorderOperation ---------------------------------------------------
279
280 // Handle the undo of reordering of bookmarks that can happen as a result of
281 // sorting a bookmark folder by name or the undo of that operation. The change
282 // of order is not recursive so only the order of the immediate children of the
283 // folder need to be restored.
284 class BookmarkReorderOperation : public BookmarkUndoOperation {
285 public:
286 BookmarkReorderOperation(Profile* profile,
287 const BookmarkNode* parent);
288 virtual ~BookmarkReorderOperation();
289
290 // UndoOperation:
291 virtual void Undo() OVERRIDE;
292
293 // BookmarkUndoOperation:
294 virtual void RenumberBookmarkId(int64 old_id, int64 new_id) OVERRIDE;
295
296 private:
297 int64 parent_id_;
298 std::vector<int64> ordered_bookmarks_;
299
300 DISALLOW_COPY_AND_ASSIGN(BookmarkReorderOperation);
301 };
302
303 BookmarkReorderOperation::BookmarkReorderOperation(Profile* profile,
304 const BookmarkNode* parent)
305 : BookmarkUndoOperation(profile),
306 parent_id_(parent->id()) {
307 ordered_bookmarks_.resize(parent->child_count());
308 for (int i = 0; i < parent->child_count(); ++i)
309 ordered_bookmarks_[i] = parent->GetChild(i)->id();
310 }
311
312 BookmarkReorderOperation::~BookmarkReorderOperation() {
313 }
314
315 void BookmarkReorderOperation::Undo() {
316 BookmarkModel* model = GetBookmarkModel();
317 const BookmarkNode* parent = model->GetNodeByID(parent_id_);
318 DCHECK(parent);
319
320 std::vector<const BookmarkNode*> ordered_nodes;
321 for (size_t i = 0; i < ordered_bookmarks_.size(); ++i)
322 ordered_nodes.push_back(model->GetNodeByID(ordered_bookmarks_[i]));
323
324 model->ReorderChildren(parent, ordered_nodes);
325 }
326
327 void BookmarkReorderOperation::RenumberBookmarkId(int64 old_id, int64 new_id) {
328 if (parent_id_ == old_id)
329 parent_id_ = new_id;
330 for (size_t i = 0; i < ordered_bookmarks_.size(); ++i) {
331 if (ordered_bookmarks_[i] == old_id)
332 ordered_bookmarks_[i] = new_id;
333 }
334 }
335
336 } // namespace
337
338 // BookmarkUndoService --------------------------------------------------------
339
340 BookmarkUndoService::BookmarkUndoService(Profile* profile) : profile_(profile) {
341 BookmarkModelFactory::GetForProfile(profile_)->AddObserver(this);
342 }
343
344 BookmarkUndoService::~BookmarkUndoService() {
345 BookmarkModelFactory::GetForProfile(profile_)->RemoveObserver(this);
346 }
347
348 void BookmarkUndoService::OnBookmarkRenumbered(int64 old_id, int64 new_id) {
349 std::vector<UndoOperation*> all_operations =
350 undo_manager()->GetAllUndoOperations();
351 for (std::vector<UndoOperation*>::iterator it = all_operations.begin();
352 it != all_operations.end(); ++it) {
353 static_cast<BookmarkUndoOperation*>(*it)->RenumberBookmarkId(old_id,
354 new_id);
355 }
356 }
357
358 void BookmarkUndoService::Loaded(BookmarkModel* model, bool ids_reassigned) {
359 undo_manager_.RemoveAllOperations();
360 }
361
362 void BookmarkUndoService::BookmarkModelBeingDeleted(BookmarkModel* model) {
363 undo_manager_.RemoveAllOperations();
364 }
365
366 void BookmarkUndoService::BookmarkNodeMoved(BookmarkModel* model,
367 const BookmarkNode* old_parent,
368 int old_index,
369 const BookmarkNode* new_parent,
370 int new_index) {
371 scoped_ptr<UndoOperation> op(new BookmarkMoveOperation(profile_,
372 old_parent,
373 old_index,
374 new_parent,
375 new_index));
376 undo_manager()->AddUndoOperation(op.Pass());
377 }
378
379 void BookmarkUndoService::BookmarkNodeAdded(BookmarkModel* model,
380 const BookmarkNode* parent,
381 int index) {
382 scoped_ptr<UndoOperation> op(new BookmarkAddOperation(profile_,
383 parent,
384 index));
385 undo_manager()->AddUndoOperation(op.Pass());
386 }
387
388 void BookmarkUndoService::OnWillRemoveBookmarks(BookmarkModel* model,
389 const BookmarkNode* parent,
390 int old_index,
391 const BookmarkNode* node) {
392 scoped_ptr<UndoOperation> op(new BookmarkRemoveOperation(profile_,
393 parent,
394 old_index,
395 node));
396 undo_manager()->AddUndoOperation(op.Pass());
397 }
398
399 void BookmarkUndoService::OnWillRemoveAllBookmarks(BookmarkModel* model) {
400 ScopedGroupingAction merge_removes(undo_manager());
401 for (int i = 0; i < model->root_node()->child_count(); ++i) {
402 const BookmarkNode* permanent_node = model->root_node()->GetChild(i);
403 for (int j = permanent_node->child_count() - 1; j >= 0; --j) {
404 scoped_ptr<UndoOperation> op(new BookmarkRemoveOperation(profile_,
405 permanent_node, j, permanent_node->GetChild(j)));
406 undo_manager()->AddUndoOperation(op.Pass());
407 }
408 }
409 }
410
411 void BookmarkUndoService::OnWillChangeBookmarkNode(BookmarkModel* model,
412 const BookmarkNode* node) {
413 scoped_ptr<UndoOperation> op(new BookmarkEditOperation(profile_, node));
414 undo_manager()->AddUndoOperation(op.Pass());
415 }
416
417 void BookmarkUndoService::OnWillReorderBookmarkNode(BookmarkModel* model,
418 const BookmarkNode* node) {
419 scoped_ptr<UndoOperation> op(new BookmarkReorderOperation(profile_, node));
420 undo_manager()->AddUndoOperation(op.Pass());
421 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698