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

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, 5 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) {
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698