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