eric7/HexEdit/HexEditUndoStack.py

branch
eric7
changeset 8312
800c432b34c8
parent 8265
0090cfa83159
child 8318
962bce857696
equal deleted inserted replaced
8311:4e8b98454baa 8312:800c432b34c8
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2016 - 2021 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing the Undo stack for the hex edit widget.
8 """
9
10 import enum
11
12 from PyQt5.QtWidgets import QUndoStack, QUndoCommand
13
14
15 class HexEditCommand(enum.Enum):
16 """
17 Class implementing the edit commands.
18 """
19 INSERT = 0
20 REMOVEAT = 1
21 OVERWRITE = 2
22
23
24 class HexEditUndoCommand(QUndoCommand):
25 """
26 Class implementing the Undo command.
27 """
28 def __init__(self, chunks, cmd, pos, newByte, parent=None):
29 """
30 Constructor
31
32 @param chunks reference to the data container
33 @type HexEditChunks
34 @param cmd edit command
35 @type HexEditCommand
36 @param pos edit position
37 @type int
38 @param newByte new byte value
39 @type int (range 0 to 255)
40 @param parent reference to the parent command
41 @type QUndoCommand
42 """
43 super().__init__(parent)
44
45 self.__chunks = chunks
46 self._pos = pos
47 self._newByte = newByte
48 self._cmd = cmd
49
50 self.__wasChanged = False
51 self.__oldByte = 0
52
53 def undo(self):
54 """
55 Public method to undo the command.
56 """
57 if self._cmd == HexEditCommand.INSERT:
58 self.__chunks.removeAt(self._pos)
59 elif self._cmd == HexEditCommand.OVERWRITE:
60 self.__chunks.overwrite(self._pos, self.__oldByte)
61 self.__chunks.setDataChanged(self._pos, self.__wasChanged)
62 elif self._cmd == HexEditCommand.REMOVEAT:
63 self.__chunks.insert(self._pos, self.__oldByte)
64 self.__chunks.setDataChanged(self._pos, self.__wasChanged)
65
66 def redo(self):
67 """
68 Public method to redo the command.
69 """
70 if self._cmd == HexEditCommand.INSERT:
71 self.__chunks.insert(self._pos, self._newByte)
72 elif self._cmd == HexEditCommand.OVERWRITE:
73 self.__oldByte = self.__chunks[self._pos]
74 self.__wasChanged = self.__chunks.dataChanged(self._pos)
75 self.__chunks.overwrite(self._pos, self._newByte)
76 elif self._cmd == HexEditCommand.REMOVEAT:
77 self.__oldByte = self.__chunks[self._pos]
78 self.__wasChanged = self.__chunks.dataChanged(self._pos)
79 self.__chunks.removeAt(self._pos)
80
81 def mergeWith(self, command):
82 """
83 Public method to merge this command with another one.
84
85 @param command reference to the command to merge with
86 @type QUndoCommand
87 @return flag indicating a successful merge
88 @rtype bool
89 """
90 result = False
91
92 if (
93 self._cmd != HexEditCommand.REMOVEAT and
94 command._cmd == HexEditCommand.OVERWRITE and
95 command._pos == self._pos
96 ):
97 self._newByte = command._newByte
98 result = True
99
100 return result
101
102 def id(self):
103 """
104 Public method to get the ID of this undo command class.
105
106 @return ID of the undo command class
107 @rtype int
108 """
109 return 4242
110
111
112 class HexEditUndoStack(QUndoStack):
113 """
114 Class implementing an Undo stack for the hex edit widget.
115 """
116 def __init__(self, chunks, parent=None):
117 """
118 Constructor
119
120 @param chunks reference to the data container
121 @type HexEditChunks
122 @param parent reference to the parent object
123 @type QObject
124 """
125 super().__init__(parent)
126
127 self.__chunks = chunks
128 self.__parent = parent
129
130 def insert(self, pos, data):
131 """
132 Public method to insert a byte.
133
134 @param pos position to insert at
135 @type int
136 @param data byte to be inserted
137 @type int (range 0 to 255)
138 """
139 if pos >= 0 and pos <= self.__chunks.size():
140 uc = HexEditUndoCommand(
141 self.__chunks, HexEditCommand.INSERT, pos, data)
142 self.push(uc)
143
144 def insertByteArray(self, pos, byteArray):
145 """
146 Public method to insert bytes.
147
148 @param pos position to insert at
149 @type int
150 @param byteArray data to be inserted
151 @type byteArray or QByteArray
152 """
153 ba = bytearray(byteArray)
154
155 if pos >= 0 and pos <= self.__chunks.size():
156 txt = self.tr("Inserting %n byte(s)", "", len(ba))
157 self.beginMacro(txt)
158 for idx in range(len(ba)):
159 uc = HexEditUndoCommand(
160 self.__chunks, HexEditCommand.INSERT, pos + idx, ba[idx])
161 self.push(uc)
162 self.endMacro()
163
164 def removeAt(self, pos, length=1):
165 """
166 Public method to remove bytes.
167
168 @param pos position to remove bytes from
169 @type int
170 @param length amount of bytes to remove
171 @type int
172 """
173 if pos >= 0 and pos <= self.__chunks.size():
174 if length == 1:
175 uc = HexEditUndoCommand(
176 self.__chunks, HexEditCommand.REMOVEAT, pos, 0)
177 self.push(uc)
178 else:
179 txt = self.tr("Deleting %n byte(s)", "", length)
180 self.beginMacro(txt)
181 for _cnt in range(length):
182 uc = HexEditUndoCommand(
183 self.__chunks, HexEditCommand.REMOVEAT, pos, 0)
184 self.push(uc)
185 self.endMacro()
186
187 def overwrite(self, pos, data):
188 """
189 Public method to replace a byte.
190
191 @param pos position to replace the byte at
192 @type int
193 @param data byte to replace with
194 @type int (range 0 to 255)
195 """
196 if pos >= 0 and pos <= self.__chunks.size():
197 uc = HexEditUndoCommand(
198 self.__chunks, HexEditCommand.OVERWRITE, pos, data)
199 self.push(uc)
200
201 def overwriteByteArray(self, pos, length, byteArray):
202 """
203 Public method to replace bytes.
204
205 @param pos position to replace the bytes at
206 @type int
207 @param length amount of bytes to replace
208 @type int
209 @param byteArray bytes to replace with
210 @type bytearray or QByteArray
211 """
212 ba = bytearray(byteArray)
213
214 if pos >= 0 and pos <= self.__chunks.size():
215 txt = self.tr("Inserting %n byte(s)", "", len(ba))
216 self.beginMacro(txt)
217 self.removeAt(pos, length)
218 self.insertByteArray(pos, ba)
219 self.endMacro()

eric ide

mercurial