1 /*
2 This file is a part of
3 QVGE - Qt Visual Graph Editor
4
5 (c) 2016-2020 Ars L. Masiuk (ars.masiuk@gmail.com)
6
7 It can be used freely, maintaining the information above.
8 */
9
10
11 #include "CDiffUndoManager.h"
12 #include "CEditorScene.h"
13
14 #include <QDataStream>
15
16
CDiffUndoManager(CEditorScene & scene)17 CDiffUndoManager::CDiffUndoManager(CEditorScene & scene)
18 : m_scene(&scene)
19 {
20 }
21
reset()22 void CDiffUndoManager::reset()
23 {
24 m_redoStack.clear();
25 m_undoStack.clear();
26 m_redoStackTemp.clear();
27 m_undoStackTemp.clear();
28 m_lastState.clear();
29 }
30
addState()31 void CDiffUndoManager::addState()
32 {
33 // drop temp stacks
34 m_redoStack.clear();
35 m_undoStackTemp.clear();
36
37 // serialize & compress
38 QByteArray snap;
39 QDataStream ds(&snap, QIODevice::WriteOnly);
40 m_scene->storeTo(ds, true);
41
42 // check if 1st store
43 if (m_lastState.isEmpty() && m_undoStack.isEmpty() && m_redoStack.isEmpty())
44 {
45 m_lastState = snap;
46 return;
47 }
48
49 // push states into stacks
50 int leftDiffIndex = 0;
51 int len = qMin(snap.size(), m_lastState.size());
52 while (leftDiffIndex < len && snap[leftDiffIndex] == m_lastState[leftDiffIndex])
53 ++leftDiffIndex;
54
55 int rightDiffIndex1 = m_lastState.size() - 1;
56 int rightDiffIndex2 = snap.size() - 1;
57 while (rightDiffIndex1 >= 0 && rightDiffIndex2 >= 0
58 && rightDiffIndex1 > leftDiffIndex && rightDiffIndex2 > leftDiffIndex
59 && snap[rightDiffIndex2] == m_lastState[rightDiffIndex1])
60 --rightDiffIndex1, --rightDiffIndex2;
61
62 int len1 = rightDiffIndex1 - leftDiffIndex + 1;
63 int len2 = rightDiffIndex2 - leftDiffIndex + 1;
64
65 Command cUndo = { leftDiffIndex, len2, qCompress(m_lastState.mid(leftDiffIndex, len1)) };
66 Command cRedo = { leftDiffIndex, len1, qCompress(snap.mid(leftDiffIndex, len2)) };
67
68 m_undoStack << cUndo;
69 m_redoStackTemp << cRedo;
70
71 // write last state
72 m_lastState = snap;
73 }
74
revertState()75 void CDiffUndoManager::revertState()
76 {
77 QDataStream ds(&m_lastState, QIODevice::ReadOnly);
78 m_scene->restoreFrom(ds, true);
79 }
80
undo()81 void CDiffUndoManager::undo()
82 {
83 if (availableUndoCount())
84 {
85 Command cUndo = m_undoStack.takeLast();
86 m_lastState.replace(cUndo.index, cUndo.sizeToReplace, qUncompress(cUndo.data));
87 QDataStream ds(&m_lastState, QIODevice::ReadOnly);
88 m_scene->restoreFrom(ds, true);
89
90 m_redoStack << m_redoStackTemp.takeLast();
91 m_undoStackTemp << cUndo;
92 }
93 }
94
redo()95 void CDiffUndoManager::redo()
96 {
97 if (availableRedoCount())
98 {
99 Command cRedo = m_redoStack.takeLast();
100 m_lastState.replace(cRedo.index, cRedo.sizeToReplace, qUncompress(cRedo.data));
101 QDataStream ds(&m_lastState, QIODevice::ReadOnly);
102 m_scene->restoreFrom(ds, true);
103
104 m_undoStack << m_undoStackTemp.takeLast();
105 m_redoStackTemp << cRedo;
106 }
107 }
108
availableUndoCount() const109 int CDiffUndoManager::availableUndoCount() const
110 {
111 return m_undoStack.size();
112 }
113
availableRedoCount() const114 int CDiffUndoManager::availableRedoCount() const
115 {
116 return m_redoStack.size();
117 }
118