HexEdit/HexEditUndoStack.py

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

eric ide

mercurial