1 #include "commands.h"
2 #include <QUndoCommand>
3
4
5 // Helper class to store single byte commands
6 class CharCommand : public QUndoCommand
7 {
8 public:
9 enum CCmd {insert, removeAt, overwrite};
10
11 CharCommand(Chunks * chunks, CCmd cmd, qint64 charPos, char newChar,
12 QUndoCommand *parent=0);
13
14 void undo();
15 void redo();
16 bool mergeWith(const QUndoCommand *command);
id() const17 int id() const { return 1234; }
18
19 private:
20 Chunks * _chunks;
21 qint64 _charPos;
22 bool _wasChanged;
23 char _newChar;
24 char _oldChar;
25 CCmd _cmd;
26 };
27
CharCommand(Chunks * chunks,CCmd cmd,qint64 charPos,char newChar,QUndoCommand * parent)28 CharCommand::CharCommand(Chunks * chunks, CCmd cmd, qint64 charPos, char newChar, QUndoCommand *parent)
29 : QUndoCommand(parent)
30 {
31 _chunks = chunks;
32 _charPos = charPos;
33 _newChar = newChar;
34 _cmd = cmd;
35 _wasChanged = false;
36 _oldChar = ' ';
37 }
38
mergeWith(const QUndoCommand * command)39 bool CharCommand::mergeWith(const QUndoCommand *command)
40 {
41 const CharCommand *nextCommand = static_cast<const CharCommand *>(command);
42 bool result = false;
43
44 if (_cmd != CharCommand::removeAt)
45 {
46 if (nextCommand->_cmd == overwrite)
47 if (nextCommand->_charPos == _charPos)
48 {
49 _newChar = nextCommand->_newChar;
50 result = true;
51 }
52 }
53 return result;
54 }
55
undo()56 void CharCommand::undo()
57 {
58 switch (_cmd)
59 {
60 case insert:
61 _chunks->removeAt(_charPos);
62 break;
63 case overwrite:
64 _chunks->overwrite(_charPos, _oldChar);
65 _chunks->setDataChanged(_charPos, _wasChanged);
66 break;
67 case removeAt:
68 _chunks->insert(_charPos, _oldChar);
69 _chunks->setDataChanged(_charPos, _wasChanged);
70 break;
71 }
72 }
73
redo()74 void CharCommand::redo()
75 {
76 switch (_cmd)
77 {
78 case insert:
79 _chunks->insert(_charPos, _newChar);
80 break;
81 case overwrite:
82 _oldChar = (*_chunks)[_charPos];
83 _wasChanged = _chunks->dataChanged(_charPos);
84 _chunks->overwrite(_charPos, _newChar);
85 break;
86 case removeAt:
87 _oldChar = (*_chunks)[_charPos];
88 _wasChanged = _chunks->dataChanged(_charPos);
89 _chunks->removeAt(_charPos);
90 break;
91 }
92 }
93
UndoStack(Chunks * chunks,QObject * parent)94 UndoStack::UndoStack(Chunks * chunks, QObject * parent)
95 : QUndoStack(parent)
96 {
97 _chunks = chunks;
98 _parent = parent;
99 }
100
insert(qint64 pos,char c)101 void UndoStack::insert(qint64 pos, char c)
102 {
103 if ((pos >= 0) && (pos <= _chunks->size()))
104 {
105 QUndoCommand *cc = new CharCommand(_chunks, CharCommand::insert, pos, c);
106 this->push(cc);
107 }
108 }
109
insert(qint64 pos,const QByteArray & ba)110 void UndoStack::insert(qint64 pos, const QByteArray &ba)
111 {
112 if ((pos >= 0) && (pos <= _chunks->size()))
113 {
114 QString txt = QString(tr("Inserting %1 bytes")).arg(ba.size());
115 beginMacro(txt);
116 for (int idx=0; idx < ba.size(); idx++)
117 {
118 QUndoCommand *cc = new CharCommand(_chunks, CharCommand::insert, pos + idx, ba.at(idx));
119 this->push(cc);
120 }
121 endMacro();
122 }
123 }
124
removeAt(qint64 pos,qint64 len)125 void UndoStack::removeAt(qint64 pos, qint64 len)
126 {
127 if ((pos >= 0) && (pos < _chunks->size()))
128 {
129 if (len==1)
130 {
131 QUndoCommand *cc = new CharCommand(_chunks, CharCommand::removeAt, pos, char(0));
132 this->push(cc);
133 }
134 else
135 {
136 QString txt = QString(tr("Delete %1 chars")).arg(len);
137 beginMacro(txt);
138 for (qint64 cnt=0; cnt<len; cnt++)
139 {
140 QUndoCommand *cc = new CharCommand(_chunks, CharCommand::removeAt, pos, char(0));
141 push(cc);
142 }
143 endMacro();
144 }
145 }
146 }
147
overwrite(qint64 pos,char c)148 void UndoStack::overwrite(qint64 pos, char c)
149 {
150 if ((pos >= 0) && (pos < _chunks->size()))
151 {
152 QUndoCommand *cc = new CharCommand(_chunks, CharCommand::overwrite, pos, c);
153 this->push(cc);
154 }
155 }
156
overwrite(qint64 pos,int len,const QByteArray & ba)157 void UndoStack::overwrite(qint64 pos, int len, const QByteArray &ba)
158 {
159 if ((pos >= 0) && (pos < _chunks->size()))
160 {
161 QString txt = QString(tr("Overwrite %1 chars")).arg(len);
162 beginMacro(txt);
163 removeAt(pos, len);
164 insert(pos, ba);
165 endMacro();
166 }
167 }
168