3 // Copyright 1997-2007 by Christopher J. Madsen
4 // (C) 2019 James Hammons
6 // GUEmap is licensed under either version 2 of the GPL, or (at your option)
7 // any later version. See LICENSE file for details.
9 // Implementation of UndoRec and its derived classes
19 // UndoRec is the virtual base class for all undo records.
23 // The modification state of the document before the change that
24 // this undo record applies to was made.
27 UndoRec::UndoRec(bool modified): oldModified(modified)
38 // Get the type of undo record:
41 // The name of this undo operation (The XXX in "Undo XXX")
43 // char * UndoRec::getName() const
45 //--------------------------------------------------------------------
48 // Undo the change that this undo record applies to. This is the main entry
49 // point; it calls undoChange to actually do the work.
51 // If the document was not modified before the original change, and is
52 // modified now, then it is marked as unmodified. Otherwise, it is marked as
53 // modified. This should cause the modification flag to agree with the actual
54 // state of the document in memory vs. the file on disk.
57 // doc: The MapDoc to change
60 // A pointer to the "redo" record
61 // NULL if the operation cannot be redone
64 // undo is a one time function. After calling undo, you cannot call any
65 // other member functions; you must delete the object immediately.
67 UndoRec * UndoRec::undo(MapDoc & doc)
69 bool newModified = doc.isDirty;
71 UndoRec * redo = undoChange(doc);
73 doc.isDirty = (!oldModified && newModified ? false : true);
76 redo->oldModified = newModified;
85 // UndoAdd undoes the addition of 1 or more rooms and/or edges. Since
86 // edges are always added at the end of the list, we only need to know
87 // how many were added.
90 // edges: The number of edges that were added
91 // pageNums: The numbers of the pages that were added
92 // roomNums: The numbers of the rooms that were added
93 //--------------------------------------------------------------------
94 // Constructor for the redo record for UndoDelete:
97 // modified: The modification state of the document
98 // edgeCount: The number of edges being added
99 // rns: The numbers of the rooms being added
100 // pns: The numbers of the pages being added
102 UndoAdd::UndoAdd(bool modified, int edgeCount, RoomNumVec & rns, PageNumVec & pns): UndoRec(modified), edges(edgeCount)
110 // Constructor for a one-room addition:
113 // modified: The modification state of the document
114 // roomNum: The number of the room being added
115 // edgeCount: The number of edges being added
117 UndoAdd::UndoAdd(bool modified, RoomNum roomNum, int edgeCount): UndoRec(modified), edges(edgeCount)
119 roomNums.push_back(roomNum);
124 // Constructor for a one-page addition:
127 // modified: The modification state of the document
128 // pageNum: The number of the page being added
130 UndoAdd::UndoAdd(bool modified, short pageNum): UndoRec(modified), edges(0)
132 pageNums.push_back(pageNum);
137 // Constructor for a one-edge addition:
140 // modified: The modification state of the document
142 UndoAdd::UndoAdd(bool modified): UndoRec(modified), edges(1)
147 const char * UndoAdd::getName() const
154 // Undo the addition of rooms, edges, and/or pages:
156 UndoRec * UndoAdd::undoChange(MapDoc & doc)
158 UndoRec * redo = new UndoDelete(doc, edges, roomNums, pageNums);
161 for(int i=doc.edge.size()-1; e; e--)
164 RNConstItr r = roomNums.end();
166 while (r != roomNums.begin())
167 doc.deleteRoom(*(--r));
169 PNConstItr p = pageNums.end();
171 while (p != pageNums.begin())
172 doc.deletePage(*(--p));
179 // Class UndoChangeEdge:
181 // UndoChangeEdge is used when an existing connection is changed.
182 // Since edges are changed by being deleted and re-added, it assumes
183 // that the edge is the last one in the list. (N.B.: This is bad, but we'll roll with it for now.)
186 // edge: The original edge
187 //--------------------------------------------------------------------
191 // modified: The modification state of the document
192 // theEdge: The original edge
194 UndoChangeEdge::UndoChangeEdge(bool modified, const MapEdge & theEdge): UndoRec(modified), edge(theEdge)
199 const char * UndoChangeEdge::getName() const
201 return "Reconnection";
206 // Undo a change to a connection:
208 UndoRec * UndoChangeEdge::undoChange(MapDoc & doc)
210 const int edgeNum = doc.edge.size() - 1;
211 UndoRec * redo = new UndoChangeEdge(true, doc.edge[edgeNum]);
213 doc.deleteEdge(edgeNum);
221 // Class UndoChanges:
223 // UndoChanges combines both UndoAdd & UndoDelete in one record.
224 //--------------------------------------------------------------------
225 // Constructor for adding one room & deleting one edge:
228 // modified: The modification state of the document
229 // roomNum: The number of the room being added
230 // edgeCount: The number of edges being added
231 // edge: The edge being deleted
233 UndoChanges::UndoChanges(bool modified, RoomNum roomNum, int edgeCount, const MapEdge & edge): UndoRec(modified), add(new UndoAdd(modified, roomNum, edgeCount)), del(new UndoDelete(modified, edge))
239 // Constructor for adding one room & deleting one edge:
242 // modified: The modification state of the document
243 // roomNum: The number of the room being added (-1 if no room added)
244 // edgeCount: The number of edges being added
245 // edges: The edges being deleted
248 // edges: The vector is emptied
250 UndoChanges::UndoChanges(bool modified, int roomNum, int edgeCount, EdgeVec & edges): UndoRec(modified), del(new UndoDelete(modified, edges))
253 add = new UndoAdd(modified, roomNum, edgeCount);
255 add = new UndoAdd(modified);
260 // Constructor for removing a corner:
263 // modified: The modification state of the document
264 // roomNum: The number of the room being deleted
265 // room: The room being deleted
266 // edges: The edges being deleted
269 // edges: The vector is emptied
271 UndoChanges::UndoChanges(bool modified, RoomNum roomNum, MapRoom * room, EdgeVec & edges): UndoRec(modified), add(new UndoAdd(modified)),/* Adding 1 edge */ del(new UndoDelete(modified, edges))
273 static_cast<UndoDelete *>(del)->addRooms(1);
274 static_cast<UndoDelete *>(del)->addRoom(0, roomNum, room);
278 const char * UndoChanges::getName() const
280 return "Change"; // FIXME better name
284 UndoRec * UndoChanges::undoChange(MapDoc & doc)
286 UndoRec * redo = NULL;
288 UndoRec * newDel = add->undoChange(doc);
291 add = del->undoChange(doc);
305 // UndoDelete undoes the deletion of 1 or more rooms and/or edges. Edges are
306 // restored to the end of the list, but rooms regain their original numbers.
310 // The edges that were deleted.
311 // They are stored with the original room numbers.
313 // The pages that were deleted.
315 // The numbers of the pages that were deleted.
317 // The rooms that were deleted.
319 // The numbers of the rooms that were deleted.
320 //--------------------------------------------------------------------
321 // Constructor used when deleting the selection:
323 // Builds a list of the selected rooms and all edges which connect to them.
326 // doc: The document we're working with
327 // numSelected: The number of selected rooms
328 // selectedRooms: TRUE means the room is selected
329 // numSelectedPages: The number of selected pages
330 // selectedPages: TRUE means the page is selected
332 UndoDelete::UndoDelete(const MapDoc & doc, int numSelected, const ByteVec & selectedRooms, int numSelectedPages, const ByteVec & selectedPages): UndoRec(doc.isDirty)
335 addRooms(numSelected);
336 EdgeConstItr edge = doc.edge.begin();
338 for(i=doc.edge.size()-1; i>=0; edge++, i--)
340 if (selectedRooms[edge->room1] || selectedRooms[edge->room2])
341 edges.push_back(*edge);
344 pages.resize(numSelectedPages);
345 pageNums.resize(numSelectedPages);
346 PageConstItr page = doc.page.begin();
347 PageItr p = pages.begin();
348 PNItr pn = pageNums.begin();
350 for(i=0; numSelectedPages; i++)
352 if (selectedPages[i])
363 // Constructor used for the redo record for UndoAdd:
366 // doc: The document we're working with
367 // numEdges: The number of edges being deleted
368 // theRoomNums: The numbers of the rooms being deleted
369 // thePageNums: The numbers of the pages being deleted
371 UndoDelete::UndoDelete(const MapDoc & doc, int numEdges, const RoomNumVec & theRoomNums, const PageNumVec & thePageNums): UndoRec(doc.isDirty), pageNums(thePageNums), roomNums(theRoomNums)
373 edges.insert(edges.begin(), doc.edge.end() - numEdges, doc.edge.end());
375 RoomConstItr room = doc.room.getVector().begin();
376 rooms.reserve(roomNums.size());
378 for(RNConstItr r=roomNums.begin(); r!=roomNums.end(); ++r)
379 rooms.append(new MapRoom(*room[*r]));
381 PageConstItr page = doc.page.begin();
382 pages.reserve(pageNums.size());
384 for(PNConstItr p=pageNums.begin(); p!=pageNums.end(); ++p)
385 pages.push_back(page[*p]);
390 // Constructor used when deleting one edge:
393 // modified: The modification state of the document
394 // edge: The edge that was deleted
396 UndoDelete::UndoDelete(bool modified, const MapEdge & edge): UndoRec(modified)
398 edges.push_back(edge);
402 void UndoDelete::addRoom(VecSize pos, RoomNum n, MapRoom * r)
405 rooms.getVector()[pos] = r;
409 void UndoDelete::addRooms(VecSize n)
417 // Constructor used when deleting several edges:
420 // modified: The modification state of the document
421 // theEdges: The edges that were deleted
424 // theEdges: The vector is emptied
426 UndoDelete::UndoDelete(bool modified, EdgeVec & theEdges): UndoRec(modified)
428 edges.swap(theEdges);
432 const char * UndoDelete::getName() const
439 // Undo the deletion of rooms and/or edges:
441 UndoRec * UndoDelete::undoChange(MapDoc & doc)
443 ASSERT(rooms.size() == roomNums.size());
444 doc.addRooms(rooms.size());
445 RoomItr r = rooms.getVector().begin();
447 for(RNConstItr rn=roomNums.begin(); rn!=roomNums.end(); r++, rn++)
449 doc.addRoom(*rn, *r);
453 doc.addEdges(edges.size());
455 for(EdgeConstItr e=edges.begin(); e!=edges.end(); ++e)
458 ASSERT(pages.size() == pageNums.size());
459 doc.addPages(pages.size());
460 PageConstItr p = pages.begin();
462 for(PNConstItr pn=pageNums.begin(); pn!=pageNums.end(); p++, pn++)
463 doc.addPage(*pn, *p);
465 return new UndoAdd(true, edges.size(), roomNums, pageNums);
472 // UndoMove undoes room movement.
475 // offset: The amount the rooms were moved
476 // pageNums: The numbers of the pages that were moved
477 // roomNums: The numbers of the rooms that were moved
478 //--------------------------------------------------------------------
479 // Constructor used after dragging the selection:
482 // modified: The modification state of the document
483 // moved: The distance the rooms were moved
484 // numSelected: The number of selected rooms
485 // selectedRooms: TRUE means the room is selected
486 // numSelectedPages: The number of selected pages
487 // selectedPages: TRUE means the page is selected
489 UndoMove::UndoMove(bool modified, const QSize & moved, int numSelected, const ByteVec & selectedRooms, int numSelectedPages, const ByteVec & selectedPages): UndoRec(modified), offset(moved)
492 pageNums.resize(numSelectedPages);
494 for(i=0, j=0; i<numSelectedPages; j++)
496 if (selectedPages[j])
500 roomNums.resize(numSelected);
502 for(i=0, j=0; i<numSelected; j++)
504 if (selectedRooms[j])
511 // Constructor used for the redo record:
514 // modified: The modification state of the document
515 // moved: The distance the rooms were moved
516 // rooms: The numbers of the rooms being moved
517 // pages: The numbers of the pages being moved
520 // rooms & pages: Empty
522 UndoMove::UndoMove(bool modified, const QSize & moved, RoomNumVec & rooms, PageNumVec & pages): UndoRec(modified), offset(moved)
524 pageNums.swap(pages);
525 roomNums.swap(rooms);
529 const char * UndoMove::getName() const
536 // Undo room movement
538 UndoRec * UndoMove::undoChange(MapDoc & doc)
542 for(PNConstItr p=pageNums.begin(); p!=pageNums.end(); p++)
543 doc.movePage(*p, offset);
545 for(RNConstItr r=roomNums.begin(); r!=roomNums.end(); r++)
546 doc.moveRoom(*r, offset);
548 return new UndoMove(false, offset, roomNums, pageNums);
553 // Class UndoPaginate:
555 // UndoPaginate undoes a repagination.
558 // pages: The old pages
559 //--------------------------------------------------------------------
562 // This removes the pages from the document.
565 // doc: The document we're working with
567 UndoPaginate::UndoPaginate(MapDoc & doc): UndoRec(doc.isDirty)
569 pages.swap(doc.page);
573 const PageVec & UndoPaginate::getPages() const
579 const char * UndoPaginate::getName() const
581 return "Page Layout";
586 // Undo the deletion of rooms and/or edges:
588 UndoRec * UndoPaginate::undoChange(MapDoc & doc)
590 UndoRec * redo = new UndoPaginate(doc);
591 pages.swap(doc.page);
592 doc.UpdateAllViews(NULL, dupPageCount, NULL);
599 // Class UndoRoomInfo:
601 // UndoRoomInfo undoes changes made in the Room Properties dialog.
602 // Currently, this is only the room name.
605 // num: The number of the room that was modified
606 // room: The room information
607 //--------------------------------------------------------------------
611 // doc: The document we're working with
612 // roomNum: The number of the room being modified
614 UndoRoomInfo::UndoRoomInfo(const MapDoc & doc, RoomNum roomNum): UndoRec(doc.isDirty), num(roomNum), room(doc.room[roomNum])
619 const char * UndoRoomInfo::getName() const
621 return "Room Information";
626 // Undo a change in room information:
628 UndoRec * UndoRoomInfo::undoChange(MapDoc & doc)
630 UndoRec * redo = new UndoRoomInfo(doc, num);
632 doc.setRoomName(num, room.name.c_str());
633 doc.setRoomNote(num, room.note.c_str());