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

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: Incorporates changes from other CLs. 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;
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 }
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