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

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

Powered by Google App Engine
This is Rietveld 408576698