src/eric7/HexEdit/HexEditWidget.py

branch
eric7
changeset 9221
bf71ee032bb4
parent 9209
b99e7fd55fd3
child 9413
80c06d472826
equal deleted inserted replaced
9220:e9e7eca7efee 9221:bf71ee032bb4
8 """ 8 """
9 9
10 import math 10 import math
11 11
12 from PyQt6.QtCore import ( 12 from PyQt6.QtCore import (
13 pyqtSignal, pyqtSlot, Qt, QByteArray, QTimer, QRect, QBuffer, QIODevice 13 pyqtSignal,
14 pyqtSlot,
15 Qt,
16 QByteArray,
17 QTimer,
18 QRect,
19 QBuffer,
20 QIODevice,
14 ) 21 )
15 from PyQt6.QtGui import QFont, QPalette, QKeySequence, QPainter 22 from PyQt6.QtGui import QFont, QPalette, QKeySequence, QPainter
16 from PyQt6.QtWidgets import QAbstractScrollArea, QApplication 23 from PyQt6.QtWidgets import QAbstractScrollArea, QApplication
17 24
18 from EricWidgets.EricApplication import ericApp 25 from EricWidgets.EricApplication import ericApp
24 31
25 32
26 class HexEditWidget(QAbstractScrollArea): 33 class HexEditWidget(QAbstractScrollArea):
27 """ 34 """
28 Class implementing an editor for binary data. 35 Class implementing an editor for binary data.
29 36
30 @signal currentAddressChanged(address) emitted to indicate the new 37 @signal currentAddressChanged(address) emitted to indicate the new
31 cursor position 38 cursor position
32 @signal currentSizeChanged(size) emitted to indicate the new size of 39 @signal currentSizeChanged(size) emitted to indicate the new size of
33 the data 40 the data
34 @signal dataChanged(modified) emitted to indicate a change of the data 41 @signal dataChanged(modified) emitted to indicate a change of the data
39 @signal canRedoChanged(bool) emitted after the redo status has changed 46 @signal canRedoChanged(bool) emitted after the redo status has changed
40 @signal canUndoChanged(bool) emitted after the undo status has changed 47 @signal canUndoChanged(bool) emitted after the undo status has changed
41 @signal selectionAvailable(bool) emitted to signal a change of the 48 @signal selectionAvailable(bool) emitted to signal a change of the
42 selection 49 selection
43 """ 50 """
51
44 currentAddressChanged = pyqtSignal(int) 52 currentAddressChanged = pyqtSignal(int)
45 currentSizeChanged = pyqtSignal(int) 53 currentSizeChanged = pyqtSignal(int)
46 dataChanged = pyqtSignal(bool) 54 dataChanged = pyqtSignal(bool)
47 overwriteModeChanged = pyqtSignal(bool) 55 overwriteModeChanged = pyqtSignal(bool)
48 readOnlyChanged = pyqtSignal(bool) 56 readOnlyChanged = pyqtSignal(bool)
49 canRedoChanged = pyqtSignal(bool) 57 canRedoChanged = pyqtSignal(bool)
50 canUndoChanged = pyqtSignal(bool) 58 canUndoChanged = pyqtSignal(bool)
51 selectionAvailable = pyqtSignal(bool) 59 selectionAvailable = pyqtSignal(bool)
52 60
53 HEXCHARS_PER_LINE = 47 61 HEXCHARS_PER_LINE = 47
54 BYTES_PER_LINE = 16 62 BYTES_PER_LINE = 16
55 63
56 def __init__(self, parent=None): 64 def __init__(self, parent=None):
57 """ 65 """
58 Constructor 66 Constructor
59 67
60 @param parent refernce to the parent widget 68 @param parent refernce to the parent widget
61 @type QWidget 69 @type QWidget
62 """ 70 """
63 super().__init__(parent) 71 super().__init__(parent)
64 72
65 # Properties 73 # Properties
66 self.__addressArea = True 74 self.__addressArea = True
67 # switch the address area on/off 75 # switch the address area on/off
68 self.__addressOffset = 0 76 self.__addressOffset = 0
69 # offset into the shown address range 77 # offset into the shown address range
79 # set overwrite mode on/off 87 # set overwrite mode on/off
80 self.__readOnly = False 88 self.__readOnly = False
81 # set read only mode on/off 89 # set read only mode on/off
82 self.__cursorPosition = 0 90 self.__cursorPosition = 0
83 # absolute position of cursor, 1 Byte == 2 tics 91 # absolute position of cursor, 1 Byte == 2 tics
84 92
85 self.__addrDigits = 0 93 self.__addrDigits = 0
86 self.__addrSeparators = 0 94 self.__addrSeparators = 0
87 self.__blink = True 95 self.__blink = True
88 self.__bData = QBuffer() 96 self.__bData = QBuffer()
89 self.__cursorRect = QRect() 97 self.__cursorRect = QRect()
92 self.__hexDataShown = bytearray() 100 self.__hexDataShown = bytearray()
93 self.__lastEventSize = 0 101 self.__lastEventSize = 0
94 self.__markedShown = bytearray() 102 self.__markedShown = bytearray()
95 self.__modified = False 103 self.__modified = False
96 self.__rowsShown = 0 104 self.__rowsShown = 0
97 105
98 # pixel related attributes (starting with __px) 106 # pixel related attributes (starting with __px)
99 self.__pxCharWidth = 0 107 self.__pxCharWidth = 0
100 self.__pxCharHeight = 0 108 self.__pxCharHeight = 0
101 self.__pxPosHexX = 0 109 self.__pxPosHexX = 0
102 self.__pxPosAdrX = 0 110 self.__pxPosAdrX = 0
106 self.__pxGapHexAscii = 0 114 self.__pxGapHexAscii = 0
107 self.__pxSelectionSub = 0 115 self.__pxSelectionSub = 0
108 self.__pxCursorWidth = 0 116 self.__pxCursorWidth = 0
109 self.__pxCursorX = 0 117 self.__pxCursorX = 0
110 self.__pxCursorY = 0 118 self.__pxCursorY = 0
111 119
112 # absolute byte position related attributes (starting with __b) 120 # absolute byte position related attributes (starting with __b)
113 self.__bSelectionBegin = 0 121 self.__bSelectionBegin = 0
114 self.__bSelectionEnd = 0 122 self.__bSelectionEnd = 0
115 self.__bSelectionInit = 0 123 self.__bSelectionInit = 0
116 self.__bPosFirst = 0 124 self.__bPosFirst = 0
117 self.__bPosLast = 0 125 self.__bPosLast = 0
118 self.__bPosCurrent = 0 126 self.__bPosCurrent = 0
119 127
120 self.__chunks = HexEditChunks() 128 self.__chunks = HexEditChunks()
121 self.__undoStack = HexEditUndoStack(self.__chunks, self) 129 self.__undoStack = HexEditUndoStack(self.__chunks, self)
122 if Globals.isWindowsPlatform(): 130 if Globals.isWindowsPlatform():
123 self.setFont(QFont(["Courier"], 10)) 131 self.setFont(QFont(["Courier"], 10))
124 else: 132 else:
125 self.setFont(QFont(["Monospace"], 10)) 133 self.setFont(QFont(["Monospace"], 10))
126 134
127 self.__cursorTimer = QTimer() 135 self.__cursorTimer = QTimer()
128 self.__cursorTimer.timeout.connect(self.__updateCursor) 136 self.__cursorTimer.timeout.connect(self.__updateCursor)
129 137
130 self.verticalScrollBar().valueChanged.connect(self.__adjust) 138 self.verticalScrollBar().valueChanged.connect(self.__adjust)
131 139
132 self.__undoStack.indexChanged.connect(self.__dataChangedPrivate) 140 self.__undoStack.indexChanged.connect(self.__dataChangedPrivate)
133 self.__undoStack.canRedoChanged.connect(self.__canRedoChanged) 141 self.__undoStack.canRedoChanged.connect(self.__canRedoChanged)
134 self.__undoStack.canUndoChanged.connect(self.__canUndoChanged) 142 self.__undoStack.canUndoChanged.connect(self.__canUndoChanged)
135 143
136 self.readOnlyChanged.connect(self.__canRedoChanged) 144 self.readOnlyChanged.connect(self.__canRedoChanged)
137 self.readOnlyChanged.connect(self.__canUndoChanged) 145 self.readOnlyChanged.connect(self.__canUndoChanged)
138 146
139 self.__cursorTimer.setInterval(500) 147 self.__cursorTimer.setInterval(500)
140 self.__cursorTimer.start() 148 self.__cursorTimer.start()
141 149
142 self.setAddressWidth(4) 150 self.setAddressWidth(4)
143 self.setAddressArea(True) 151 self.setAddressArea(True)
144 self.setAsciiArea(True) 152 self.setAsciiArea(True)
145 self.setOverwriteMode(True) 153 self.setOverwriteMode(True)
146 self.setHighlighting(True) 154 self.setHighlighting(True)
147 self.setReadOnly(False) 155 self.setReadOnly(False)
148 156
149 self.__initialize() 157 self.__initialize()
150 158
151 def undoStack(self): 159 def undoStack(self):
152 """ 160 """
153 Public method to get a reference to the undo stack. 161 Public method to get a reference to the undo stack.
154 162
155 @return reference to the undo stack 163 @return reference to the undo stack
156 @rtype HexEditUndoStack 164 @rtype HexEditUndoStack
157 """ 165 """
158 return self.__undoStack 166 return self.__undoStack
159 167
160 @pyqtSlot() 168 @pyqtSlot()
161 def __canRedoChanged(self): 169 def __canRedoChanged(self):
162 """ 170 """
163 Private slot handling changes of the Redo state. 171 Private slot handling changes of the Redo state.
164 """ 172 """
165 self.canRedoChanged.emit( 173 self.canRedoChanged.emit(self.__undoStack.canRedo() and not self.__readOnly)
166 self.__undoStack.canRedo() and not self.__readOnly) 174
167
168 @pyqtSlot() 175 @pyqtSlot()
169 def __canUndoChanged(self): 176 def __canUndoChanged(self):
170 """ 177 """
171 Private slot handling changes of the Undo state. 178 Private slot handling changes of the Undo state.
172 """ 179 """
173 self.canUndoChanged.emit( 180 self.canUndoChanged.emit(self.__undoStack.canUndo() and not self.__readOnly)
174 self.__undoStack.canUndo() and not self.__readOnly) 181
175
176 def addressArea(self): 182 def addressArea(self):
177 """ 183 """
178 Public method to get the address area visibility. 184 Public method to get the address area visibility.
179 185
180 @return flag indicating the address area visibility 186 @return flag indicating the address area visibility
181 @rtype bool 187 @rtype bool
182 """ 188 """
183 return self.__addressArea 189 return self.__addressArea
184 190
185 def setAddressArea(self, on): 191 def setAddressArea(self, on):
186 """ 192 """
187 Public method to set the address area visibility. 193 Public method to set the address area visibility.
188 194
189 @param on flag indicating the address area visibility 195 @param on flag indicating the address area visibility
190 @type bool 196 @type bool
191 """ 197 """
192 self.__addressArea = on 198 self.__addressArea = on
193 self.__adjust() 199 self.__adjust()
194 self.setCursorPosition(self.__cursorPosition) 200 self.setCursorPosition(self.__cursorPosition)
195 self.viewport().update() 201 self.viewport().update()
196 202
197 def addressOffset(self): 203 def addressOffset(self):
198 """ 204 """
199 Public method to get the address offset. 205 Public method to get the address offset.
200 206
201 @return address offset 207 @return address offset
202 @rtype int 208 @rtype int
203 """ 209 """
204 return self.__addressOffset 210 return self.__addressOffset
205 211
206 def setAddressOffset(self, offset): 212 def setAddressOffset(self, offset):
207 """ 213 """
208 Public method to set the address offset. 214 Public method to set the address offset.
209 215
210 @param offset address offset 216 @param offset address offset
211 @type int 217 @type int
212 """ 218 """
213 self.__addressOffset = offset 219 self.__addressOffset = offset
214 self.__adjust() 220 self.__adjust()
215 self.setCursorPosition(self.__cursorPosition) 221 self.setCursorPosition(self.__cursorPosition)
216 self.viewport().update() 222 self.viewport().update()
217 223
218 def addressWidth(self): 224 def addressWidth(self):
219 """ 225 """
220 Public method to get the width of the address area in 226 Public method to get the width of the address area in
221 characters. 227 characters.
222 228
223 Note: The address area width is always a multiple of four. 229 Note: The address area width is always a multiple of four.
224 230
225 @return minimum width of the address area 231 @return minimum width of the address area
226 @rtype int 232 @rtype int
227 """ 233 """
228 size = self.__chunks.size() 234 size = self.__chunks.size()
229 n = 1 235 n = 1
238 size //= 0x100 244 size //= 0x100
239 if size > 0x10: 245 if size > 0x10:
240 n += 1 246 n += 1
241 size //= 0x10 247 size //= 0x10
242 n = int(math.ceil(n / 4)) * 4 248 n = int(math.ceil(n / 4)) * 4
243 249
244 if n > self.__addressWidth: 250 if n > self.__addressWidth:
245 return n 251 return n
246 else: 252 else:
247 return self.__addressWidth 253 return self.__addressWidth
248 254
249 def setAddressWidth(self, width): 255 def setAddressWidth(self, width):
250 """ 256 """
251 Public method to set the width of the address area. 257 Public method to set the width of the address area.
252 258
253 Note: The address area width is always a multiple of four. 259 Note: The address area width is always a multiple of four.
254 The given value will be adjusted as required. 260 The given value will be adjusted as required.
255 261
256 @param width width of the address area in characters 262 @param width width of the address area in characters
257 @type int 263 @type int
258 """ 264 """
259 self.__addressWidth = int(math.ceil(width / 4)) * 4 265 self.__addressWidth = int(math.ceil(width / 4)) * 4
260 self.__adjust() 266 self.__adjust()
261 self.setCursorPosition(self.__cursorPosition) 267 self.setCursorPosition(self.__cursorPosition)
262 self.viewport().update() 268 self.viewport().update()
263 269
264 def asciiArea(self): 270 def asciiArea(self):
265 """ 271 """
266 Public method to get the visibility of the ASCII area. 272 Public method to get the visibility of the ASCII area.
267 273
268 @return visibility of the ASCII area 274 @return visibility of the ASCII area
269 @rtype bool 275 @rtype bool
270 """ 276 """
271 return self.__asciiArea 277 return self.__asciiArea
272 278
273 def setAsciiArea(self, on): 279 def setAsciiArea(self, on):
274 """ 280 """
275 Public method to set the visibility of the ASCII area. 281 Public method to set the visibility of the ASCII area.
276 282
277 @param on flag indicating the visibility of the ASCII area 283 @param on flag indicating the visibility of the ASCII area
278 @type bool 284 @type bool
279 """ 285 """
280 self.__asciiArea = on 286 self.__asciiArea = on
281 self.viewport().update() 287 self.viewport().update()
282 288
283 def cursorPosition(self): 289 def cursorPosition(self):
284 """ 290 """
285 Public method to get the cursor position. 291 Public method to get the cursor position.
286 292
287 @return cursor position 293 @return cursor position
288 @rtype int 294 @rtype int
289 """ 295 """
290 return self.__cursorPosition 296 return self.__cursorPosition
291 297
292 def setCursorPosition(self, pos): 298 def setCursorPosition(self, pos):
293 """ 299 """
294 Public method to set the cursor position. 300 Public method to set the cursor position.
295 301
296 @param pos cursor position 302 @param pos cursor position
297 @type int 303 @type int
298 """ 304 """
299 # step 1: delete old cursor 305 # step 1: delete old cursor
300 self.__blink = False 306 self.__blink = False
301 self.viewport().update(self.__cursorRect) 307 self.viewport().update(self.__cursorRect)
302 if self.__asciiArea: 308 if self.__asciiArea:
303 self.viewport().update(self.__cursorRectAscii) 309 self.viewport().update(self.__cursorRectAscii)
304 310
305 # step 2: check, if cursor is in range 311 # step 2: check, if cursor is in range
306 if self.__overwriteMode and pos > (self.__chunks.size() * 2 - 1): 312 if self.__overwriteMode and pos > (self.__chunks.size() * 2 - 1):
307 pos = self.__chunks.size() * 2 - 1 313 pos = self.__chunks.size() * 2 - 1
308 if (not self.__overwriteMode) and pos > (self.__chunks.size() * 2): 314 if (not self.__overwriteMode) and pos > (self.__chunks.size() * 2):
309 pos = self.__chunks.size() * 2 315 pos = self.__chunks.size() * 2
310 if pos < 0: 316 if pos < 0:
311 pos = 0 317 pos = 0
312 318
313 # step 3: calculate new position of cursor 319 # step 3: calculate new position of cursor
314 self.__cursorPosition = pos 320 self.__cursorPosition = pos
315 self.__bPosCurrent = pos // 2 321 self.__bPosCurrent = pos // 2
316 self.__pxCursorY = ( 322 self.__pxCursorY = (
317 ((pos // 2 - self.__bPosFirst) // self.BYTES_PER_LINE + 1) * 323 (pos // 2 - self.__bPosFirst) // self.BYTES_PER_LINE + 1
318 self.__pxCharHeight) 324 ) * self.__pxCharHeight
319 x = (pos % (2 * self.BYTES_PER_LINE)) 325 x = pos % (2 * self.BYTES_PER_LINE)
320 self.__pxCursorX = ( 326 self.__pxCursorX = (
321 (((x // 2) * 3) + (x % 2)) * self.__pxCharWidth + self.__pxPosHexX) 327 ((x // 2) * 3) + (x % 2)
322 328 ) * self.__pxCharWidth + self.__pxPosHexX
329
323 self.__setHexCursorRect() 330 self.__setHexCursorRect()
324 331
325 # step 4: calculate position of ASCII cursor 332 # step 4: calculate position of ASCII cursor
326 x = self.__bPosCurrent % self.BYTES_PER_LINE 333 x = self.__bPosCurrent % self.BYTES_PER_LINE
327 self.__cursorRectAscii = QRect( 334 self.__cursorRectAscii = QRect(
328 self.__pxPosAsciiX + x * self.__pxCharWidth - 1, 335 self.__pxPosAsciiX + x * self.__pxCharWidth - 1,
329 self.__pxCursorY - self.__pxCharHeight + 4, 336 self.__pxCursorY - self.__pxCharHeight + 4,
330 self.__pxCharWidth + 1, self.__pxCharHeight + 1) 337 self.__pxCharWidth + 1,
331 338 self.__pxCharHeight + 1,
339 )
340
332 # step 5: draw new cursors 341 # step 5: draw new cursors
333 self.__blink = True 342 self.__blink = True
334 self.viewport().update(self.__cursorRect) 343 self.viewport().update(self.__cursorRect)
335 if self.__asciiArea: 344 if self.__asciiArea:
336 self.viewport().update(self.__cursorRectAscii) 345 self.viewport().update(self.__cursorRectAscii)
337 self.currentAddressChanged.emit(self.__bPosCurrent) 346 self.currentAddressChanged.emit(self.__bPosCurrent)
338 347
339 def __setHexCursorRect(self): 348 def __setHexCursorRect(self):
340 """ 349 """
341 Private method to set the cursor. 350 Private method to set the cursor.
342 """ 351 """
343 if self.__overwriteMode: 352 if self.__overwriteMode:
344 self.__cursorRect = QRect( 353 self.__cursorRect = QRect(
345 self.__pxCursorX, self.__pxCursorY + self.__pxCursorWidth, 354 self.__pxCursorX,
346 self.__pxCharWidth, self.__pxCursorWidth) 355 self.__pxCursorY + self.__pxCursorWidth,
356 self.__pxCharWidth,
357 self.__pxCursorWidth,
358 )
347 else: 359 else:
348 self.__cursorRect = QRect( 360 self.__cursorRect = QRect(
349 self.__pxCursorX, self.__pxCursorY - self.__pxCharHeight + 4, 361 self.__pxCursorX,
350 self.__pxCursorWidth, self.__pxCharHeight) 362 self.__pxCursorY - self.__pxCharHeight + 4,
351 363 self.__pxCursorWidth,
364 self.__pxCharHeight,
365 )
366
352 def cursorBytePosition(self): 367 def cursorBytePosition(self):
353 """ 368 """
354 Public method to get the cursor position in bytes. 369 Public method to get the cursor position in bytes.
355 370
356 @return cursor position in bytes 371 @return cursor position in bytes
357 @rtype int 372 @rtype int
358 """ 373 """
359 return self.__bPosCurrent 374 return self.__bPosCurrent
360 375
361 def setCursorBytePosition(self, pos): 376 def setCursorBytePosition(self, pos):
362 """ 377 """
363 Public method to set the cursor position in bytes. 378 Public method to set the cursor position in bytes.
364 379
365 @param pos cursor position in bytes 380 @param pos cursor position in bytes
366 @type int 381 @type int
367 """ 382 """
368 self.setCursorPosition(pos * 2) 383 self.setCursorPosition(pos * 2)
369 384
370 def goto(self, offset, fromCursor=False, backwards=False, 385 def goto(self, offset, fromCursor=False, backwards=False, extendSelection=False):
371 extendSelection=False):
372 """ 386 """
373 Public method to move the cursor. 387 Public method to move the cursor.
374 388
375 @param offset offset to move to 389 @param offset offset to move to
376 @type int 390 @type int
377 @param fromCursor flag indicating a move relative to the current cursor 391 @param fromCursor flag indicating a move relative to the current cursor
378 @type bool 392 @type bool
379 @param backwards flag indicating a backwards move 393 @param backwards flag indicating a backwards move
389 else: 403 else:
390 if backwards: 404 if backwards:
391 newPos = self.__chunks.size() - offset 405 newPos = self.__chunks.size() - offset
392 else: 406 else:
393 newPos = offset 407 newPos = offset
394 408
395 self.setCursorBytePosition(newPos) 409 self.setCursorBytePosition(newPos)
396 if extendSelection: 410 if extendSelection:
397 self.__setSelection(self.__cursorPosition) 411 self.__setSelection(self.__cursorPosition)
398 else: 412 else:
399 self.__resetSelection(self.__cursorPosition) 413 self.__resetSelection(self.__cursorPosition)
400 414
401 self.__refresh() 415 self.__refresh()
402 416
403 def data(self): 417 def data(self):
404 """ 418 """
405 Public method to get the binary data. 419 Public method to get the binary data.
406 420
407 @return binary data 421 @return binary data
408 @rtype bytearray 422 @rtype bytearray
409 """ 423 """
410 return self.__chunks.data(0, -1) 424 return self.__chunks.data(0, -1)
411 425
412 def setData(self, dataOrDevice): 426 def setData(self, dataOrDevice):
413 """ 427 """
414 Public method to set the data to show. 428 Public method to set the data to show.
415 429
416 @param dataOrDevice byte array or device containing the data 430 @param dataOrDevice byte array or device containing the data
417 @type bytes, bytearray, QByteArray or QIODevice 431 @type bytes, bytearray, QByteArray or QIODevice
418 @return flag indicating success 432 @return flag indicating success
419 @rtype bool 433 @rtype bool
420 @exception TypeError raised to indicate a wrong parameter type 434 @exception TypeError raised to indicate a wrong parameter type
421 """ 435 """
422 if not isinstance(dataOrDevice, (bytes, bytearray, QByteArray, 436 if not isinstance(dataOrDevice, (bytes, bytearray, QByteArray, QIODevice)):
423 QIODevice)):
424 raise TypeError( 437 raise TypeError(
425 "setData: parameter must be bytes, bytearray, " 438 "setData: parameter must be bytes, bytearray, "
426 "QByteArray or QIODevice") 439 "QByteArray or QIODevice"
427 440 )
441
428 if isinstance(dataOrDevice, (bytes, bytearray, QByteArray)): 442 if isinstance(dataOrDevice, (bytes, bytearray, QByteArray)):
429 self.__data = bytearray(dataOrDevice) 443 self.__data = bytearray(dataOrDevice)
430 self.__bData.setData(self.__data) 444 self.__bData.setData(self.__data)
431 return self.__setData(self.__bData) 445 return self.__setData(self.__bData)
432 else: 446 else:
433 return self.__setData(dataOrDevice) 447 return self.__setData(dataOrDevice)
434 448
435 def __setData(self, ioDevice): 449 def __setData(self, ioDevice):
436 """ 450 """
437 Private method to set the data to show. 451 Private method to set the data to show.
438 452
439 @param ioDevice device containing the data 453 @param ioDevice device containing the data
440 @type QIODevice 454 @type QIODevice
441 @return flag indicating success 455 @return flag indicating success
442 @rtype bool 456 @rtype bool
443 """ 457 """
444 ok = self.__chunks.setIODevice(ioDevice) 458 ok = self.__chunks.setIODevice(ioDevice)
445 self.__initialize() 459 self.__initialize()
446 self.__dataChangedPrivate() 460 self.__dataChangedPrivate()
447 return ok 461 return ok
448 462
449 def highlighting(self): 463 def highlighting(self):
450 """ 464 """
451 Public method to get the highlighting state. 465 Public method to get the highlighting state.
452 466
453 @return highlighting state 467 @return highlighting state
454 @rtype bool 468 @rtype bool
455 """ 469 """
456 return self.__highlighting 470 return self.__highlighting
457 471
458 def setHighlighting(self, on): 472 def setHighlighting(self, on):
459 """ 473 """
460 Public method to set the highlighting state. 474 Public method to set the highlighting state.
461 475
462 @param on new highlighting state 476 @param on new highlighting state
463 @type bool 477 @type bool
464 """ 478 """
465 self.__highlighting = on 479 self.__highlighting = on
466 self.viewport().update() 480 self.viewport().update()
467 481
468 def overwriteMode(self): 482 def overwriteMode(self):
469 """ 483 """
470 Public method to get the overwrite mode. 484 Public method to get the overwrite mode.
471 485
472 @return overwrite mode 486 @return overwrite mode
473 @rtype bool 487 @rtype bool
474 """ 488 """
475 return self.__overwriteMode 489 return self.__overwriteMode
476 490
477 def setOverwriteMode(self, on): 491 def setOverwriteMode(self, on):
478 """ 492 """
479 Public method to set the overwrite mode. 493 Public method to set the overwrite mode.
480 494
481 @param on flag indicating the new overwrite mode 495 @param on flag indicating the new overwrite mode
482 @type bool 496 @type bool
483 """ 497 """
484 self.__overwriteMode = on 498 self.__overwriteMode = on
485 self.overwriteModeChanged.emit(self.__overwriteMode) 499 self.overwriteModeChanged.emit(self.__overwriteMode)
486 500
487 # step 1: delete old cursor 501 # step 1: delete old cursor
488 self.__blink = False 502 self.__blink = False
489 self.viewport().update(self.__cursorRect) 503 self.viewport().update(self.__cursorRect)
490 # step 2: change the cursor rectangle 504 # step 2: change the cursor rectangle
491 self.__setHexCursorRect() 505 self.__setHexCursorRect()
492 # step 3: draw new cursors 506 # step 3: draw new cursors
493 self.__blink = True 507 self.__blink = True
494 self.viewport().update(self.__cursorRect) 508 self.viewport().update(self.__cursorRect)
495 509
496 def isReadOnly(self): 510 def isReadOnly(self):
497 """ 511 """
498 Public method to test the read only state. 512 Public method to test the read only state.
499 513
500 @return flag indicating the read only state 514 @return flag indicating the read only state
501 @rtype bool 515 @rtype bool
502 """ 516 """
503 return self.__readOnly 517 return self.__readOnly
504 518
505 def setReadOnly(self, on): 519 def setReadOnly(self, on):
506 """ 520 """
507 Public method to set the read only state. 521 Public method to set the read only state.
508 522
509 @param on new read only state 523 @param on new read only state
510 @type bool 524 @type bool
511 """ 525 """
512 self.__readOnly = on 526 self.__readOnly = on
513 self.readOnlyChanged.emit(self.__readOnly) 527 self.readOnlyChanged.emit(self.__readOnly)
514 528
515 def font(self): 529 def font(self):
516 """ 530 """
517 Public method to get the font used to show the data. 531 Public method to get the font used to show the data.
518 532
519 @return font used to show the data 533 @return font used to show the data
520 @rtype QFont 534 @rtype QFont
521 """ 535 """
522 return super().font() 536 return super().font()
523 537
524 def setFont(self, font): 538 def setFont(self, font):
525 """ 539 """
526 Public method to set the font used to show the data. 540 Public method to set the font used to show the data.
527 541
528 @param font font used to show the data 542 @param font font used to show the data
529 @type QFont 543 @type QFont
530 """ 544 """
531 super().setFont(font) 545 super().setFont(font)
532 try: 546 try:
539 self.__pxGapHexAscii = 2 * self.__pxCharWidth 553 self.__pxGapHexAscii = 2 * self.__pxCharWidth
540 self.__pxCursorWidth = self.__pxCharHeight // 7 554 self.__pxCursorWidth = self.__pxCharHeight // 7
541 self.__pxSelectionSub = self.fontMetrics().descent() 555 self.__pxSelectionSub = self.fontMetrics().descent()
542 self.__adjust() 556 self.__adjust()
543 self.viewport().update() 557 self.viewport().update()
544 558
545 def dataAt(self, pos, count=-1): 559 def dataAt(self, pos, count=-1):
546 """ 560 """
547 Public method to get data from a given position. 561 Public method to get data from a given position.
548 562
549 @param pos position to get data from 563 @param pos position to get data from
550 @type int 564 @type int
551 @param count amount of bytes to get 565 @param count amount of bytes to get
552 @type int 566 @type int
553 @return requested data 567 @return requested data
554 @rtype bytearray 568 @rtype bytearray
555 """ 569 """
556 return bytearray(self.__chunks.data(pos, count)) 570 return bytearray(self.__chunks.data(pos, count))
557 571
558 def write(self, device, pos=0, count=-1): 572 def write(self, device, pos=0, count=-1):
559 """ 573 """
560 Public method to write data from a given position to a device. 574 Public method to write data from a given position to a device.
561 575
562 @param device device to write to 576 @param device device to write to
563 @type QIODevice 577 @type QIODevice
564 @param pos position to start the write at 578 @param pos position to start the write at
565 @type int 579 @type int
566 @param count amount of bytes to write 580 @param count amount of bytes to write
567 @type int 581 @type int
568 @return flag indicating success 582 @return flag indicating success
569 @rtype bool 583 @rtype bool
570 """ 584 """
571 return self.__chunks.write(device, pos, count) 585 return self.__chunks.write(device, pos, count)
572 586
573 def insert(self, pos, ch): 587 def insert(self, pos, ch):
574 """ 588 """
575 Public method to insert a byte. 589 Public method to insert a byte.
576 590
577 @param pos position to insert the byte at 591 @param pos position to insert the byte at
578 @type int 592 @type int
579 @param ch byte to insert 593 @param ch byte to insert
580 @type int in the range 0x00 to 0xff 594 @type int in the range 0x00 to 0xff
581 """ 595 """
582 if ch in range(0, 256): 596 if ch in range(0, 256):
583 self.__undoStack.insert(pos, ch) 597 self.__undoStack.insert(pos, ch)
584 self.__refresh() 598 self.__refresh()
585 599
586 def remove(self, pos, length=1): 600 def remove(self, pos, length=1):
587 """ 601 """
588 Public method to remove bytes. 602 Public method to remove bytes.
589 603
590 @param pos position to remove bytes from 604 @param pos position to remove bytes from
591 @type int 605 @type int
592 @param length amount of bytes to remove 606 @param length amount of bytes to remove
593 @type int 607 @type int
594 """ 608 """
595 self.__undoStack.removeAt(pos, length) 609 self.__undoStack.removeAt(pos, length)
596 self.__refresh() 610 self.__refresh()
597 611
598 def replace(self, pos, ch): 612 def replace(self, pos, ch):
599 """ 613 """
600 Public method to replace a byte. 614 Public method to replace a byte.
601 615
602 @param pos position to replace the byte at 616 @param pos position to replace the byte at
603 @type int 617 @type int
604 @param ch byte to replace with 618 @param ch byte to replace with
605 @type int in the range 0x00 to 0xff 619 @type int in the range 0x00 to 0xff
606 """ 620 """
607 if ch in range(0, 256): 621 if ch in range(0, 256):
608 self.__undoStack.overwrite(pos, ch) 622 self.__undoStack.overwrite(pos, ch)
609 self.__refresh() 623 self.__refresh()
610 624
611 def insertByteArray(self, pos, byteArray): 625 def insertByteArray(self, pos, byteArray):
612 """ 626 """
613 Public method to insert bytes. 627 Public method to insert bytes.
614 628
615 @param pos position to insert the bytes at 629 @param pos position to insert the bytes at
616 @type int 630 @type int
617 @param byteArray bytes to be insert 631 @param byteArray bytes to be insert
618 @type bytearray or QByteArray 632 @type bytearray or QByteArray
619 """ 633 """
620 self.__undoStack.insertByteArray(pos, bytearray(byteArray)) 634 self.__undoStack.insertByteArray(pos, bytearray(byteArray))
621 self.__refresh() 635 self.__refresh()
622 636
623 def replaceByteArray(self, pos, length, byteArray): 637 def replaceByteArray(self, pos, length, byteArray):
624 """ 638 """
625 Public method to replace bytes. 639 Public method to replace bytes.
626 640
627 @param pos position to replace the bytes at 641 @param pos position to replace the bytes at
628 @type int 642 @type int
629 @param length amount of bytes to replace 643 @param length amount of bytes to replace
630 @type int 644 @type int
631 @param byteArray bytes to replace with 645 @param byteArray bytes to replace with
632 @type bytearray or QByteArray 646 @type bytearray or QByteArray
633 """ 647 """
634 self.__undoStack.overwriteByteArray(pos, length, bytearray(byteArray)) 648 self.__undoStack.overwriteByteArray(pos, length, bytearray(byteArray))
635 self.__refresh() 649 self.__refresh()
636 650
637 def cursorPositionFromPoint(self, point): 651 def cursorPositionFromPoint(self, point):
638 """ 652 """
639 Public method to calculate a cursor position from a graphics position. 653 Public method to calculate a cursor position from a graphics position.
640 654
641 @param point graphics position 655 @param point graphics position
642 @type QPoint 656 @type QPoint
643 @return cursor position 657 @return cursor position
644 @rtype int 658 @rtype int
645 """ 659 """
646 result = -1 660 result = -1
647 if (point.x() >= self.__pxPosHexX) and ( 661 if (point.x() >= self.__pxPosHexX) and (
648 point.x() < (self.__pxPosHexX + (1 + self.HEXCHARS_PER_LINE) * 662 point.x()
649 self.__pxCharWidth)): 663 < (self.__pxPosHexX + (1 + self.HEXCHARS_PER_LINE) * self.__pxCharWidth)
664 ):
650 x = ( 665 x = (
651 (point.x() - self.__pxPosHexX - self.__pxCharWidth // 2) // 666 point.x() - self.__pxPosHexX - self.__pxCharWidth // 2
652 self.__pxCharWidth 667 ) // self.__pxCharWidth
653 )
654 x = (x // 3) * 2 + x % 3 668 x = (x // 3) * 2 + x % 3
655 y = ( 669 y = ((point.y() - 3) // self.__pxCharHeight) * 2 * self.BYTES_PER_LINE
656 ((point.y() - 3) // self.__pxCharHeight) * 2 *
657 self.BYTES_PER_LINE
658 )
659 result = self.__bPosFirst * 2 + x + y 670 result = self.__bPosFirst * 2 + x + y
660 return result 671 return result
661 672
662 def ensureVisible(self): 673 def ensureVisible(self):
663 """ 674 """
664 Public method to ensure, that the cursor is visible. 675 Public method to ensure, that the cursor is visible.
665 """ 676 """
666 if self.__cursorPosition < 2 * self.__bPosFirst: 677 if self.__cursorPosition < 2 * self.__bPosFirst:
667 self.verticalScrollBar().setValue( 678 self.verticalScrollBar().setValue(
668 self.__cursorPosition // 2 // self.BYTES_PER_LINE) 679 self.__cursorPosition // 2 // self.BYTES_PER_LINE
680 )
669 if self.__cursorPosition > ( 681 if self.__cursorPosition > (
670 (self.__bPosFirst + (self.__rowsShown - 1) * 682 (self.__bPosFirst + (self.__rowsShown - 1) * self.BYTES_PER_LINE) * 2
671 self.BYTES_PER_LINE) * 2): 683 ):
672 self.verticalScrollBar().setValue( 684 self.verticalScrollBar().setValue(
673 self.__cursorPosition // 2 // self.BYTES_PER_LINE - 685 self.__cursorPosition // 2 // self.BYTES_PER_LINE - self.__rowsShown + 1
674 self.__rowsShown + 1) 686 )
675 self.viewport().update() 687 self.viewport().update()
676 688
677 def indexOf(self, byteArray, start): 689 def indexOf(self, byteArray, start):
678 """ 690 """
679 Public method to find the first occurrence of a byte array in our data. 691 Public method to find the first occurrence of a byte array in our data.
680 692
681 @param byteArray data to search for 693 @param byteArray data to search for
682 @type bytearray or QByteArray 694 @type bytearray or QByteArray
683 @param start start position of the search 695 @param start start position of the search
684 @type int 696 @type int
685 @return position of match (or -1 if not found) 697 @return position of match (or -1 if not found)
692 self.setCursorPosition(curPos + len(byteArray) * 2) 704 self.setCursorPosition(curPos + len(byteArray) * 2)
693 self.__resetSelection(curPos) 705 self.__resetSelection(curPos)
694 self.__setSelection(curPos + len(byteArray) * 2) 706 self.__setSelection(curPos + len(byteArray) * 2)
695 self.ensureVisible() 707 self.ensureVisible()
696 return pos 708 return pos
697 709
698 def lastIndexOf(self, byteArray, start): 710 def lastIndexOf(self, byteArray, start):
699 """ 711 """
700 Public method to find the last occurrence of a byte array in our data. 712 Public method to find the last occurrence of a byte array in our data.
701 713
702 @param byteArray data to search for 714 @param byteArray data to search for
703 @type bytearray or QByteArray 715 @type bytearray or QByteArray
704 @param start start position of the search 716 @param start start position of the search
705 @type int 717 @type int
706 @return position of match (or -1 if not found) 718 @return position of match (or -1 if not found)
713 self.setCursorPosition(curPos - 1) 725 self.setCursorPosition(curPos - 1)
714 self.__resetSelection(curPos) 726 self.__resetSelection(curPos)
715 self.__setSelection(curPos + len(byteArray) * 2) 727 self.__setSelection(curPos + len(byteArray) * 2)
716 self.ensureVisible() 728 self.ensureVisible()
717 return pos 729 return pos
718 730
719 def isModified(self): 731 def isModified(self):
720 """ 732 """
721 Public method to check for any modification. 733 Public method to check for any modification.
722 734
723 @return flag indicating a modified state 735 @return flag indicating a modified state
724 @rtype bool 736 @rtype bool
725 """ 737 """
726 return self.__modified 738 return self.__modified
727 739
728 def setModified(self, modified, setCleanState=False): 740 def setModified(self, modified, setCleanState=False):
729 """ 741 """
730 Public slot to set the modified flag. 742 Public slot to set the modified flag.
731 743
732 @param modified flag indicating the new modification status 744 @param modified flag indicating the new modification status
733 @type bool 745 @type bool
734 @param setCleanState flag indicating to set the undo stack to clean 746 @param setCleanState flag indicating to set the undo stack to clean
735 @type bool 747 @type bool
736 """ 748 """
737 self.__modified = modified 749 self.__modified = modified
738 self.dataChanged.emit(modified) 750 self.dataChanged.emit(modified)
739 751
740 if not modified and setCleanState: 752 if not modified and setCleanState:
741 self.__undoStack.setClean() 753 self.__undoStack.setClean()
742 754
743 def selectionToHexString(self): 755 def selectionToHexString(self):
744 """ 756 """
745 Public method to get a hexadecimal representation of the selection. 757 Public method to get a hexadecimal representation of the selection.
746 758
747 @return hexadecimal representation of the selection 759 @return hexadecimal representation of the selection
748 @rtype str 760 @rtype str
749 """ 761 """
750 byteArray = self.__chunks.data(self.getSelectionBegin(), 762 byteArray = self.__chunks.data(
751 self.getSelectionLength()) 763 self.getSelectionBegin(), self.getSelectionLength()
764 )
752 return self.__toHex(byteArray).decode(encoding="ascii") 765 return self.__toHex(byteArray).decode(encoding="ascii")
753 766
754 def selectionToReadableString(self): 767 def selectionToReadableString(self):
755 """ 768 """
756 Public method to get a formatted representation of the selection. 769 Public method to get a formatted representation of the selection.
757 770
758 @return formatted representation of the selection 771 @return formatted representation of the selection
759 @rtype str 772 @rtype str
760 """ 773 """
761 byteArray = self.__chunks.data(self.getSelectionBegin(), 774 byteArray = self.__chunks.data(
762 self.getSelectionLength()) 775 self.getSelectionBegin(), self.getSelectionLength()
776 )
763 return self.__toReadable(byteArray) 777 return self.__toReadable(byteArray)
764 778
765 def toReadableString(self): 779 def toReadableString(self):
766 """ 780 """
767 Public method to get a formatted representation of our data. 781 Public method to get a formatted representation of our data.
768 782
769 @return formatted representation of our data 783 @return formatted representation of our data
770 @rtype str 784 @rtype str
771 """ 785 """
772 byteArray = self.__chunks.data() 786 byteArray = self.__chunks.data()
773 return self.__toReadable(byteArray) 787 return self.__toReadable(byteArray)
774 788
775 @pyqtSlot() 789 @pyqtSlot()
776 def redo(self): 790 def redo(self):
777 """ 791 """
778 Public slot to redo the last operation. 792 Public slot to redo the last operation.
779 """ 793 """
780 self.__undoStack.redo() 794 self.__undoStack.redo()
781 self.setCursorPosition(self.__chunks.pos() * 2) 795 self.setCursorPosition(self.__chunks.pos() * 2)
782 self.__refresh() 796 self.__refresh()
783 797
784 @pyqtSlot() 798 @pyqtSlot()
785 def undo(self): 799 def undo(self):
786 """ 800 """
787 Public slot to undo the last operation. 801 Public slot to undo the last operation.
788 """ 802 """
789 self.__undoStack.undo() 803 self.__undoStack.undo()
790 self.setCursorPosition(self.__chunks.pos() * 2) 804 self.setCursorPosition(self.__chunks.pos() * 2)
791 self.__refresh() 805 self.__refresh()
792 806
793 @pyqtSlot() 807 @pyqtSlot()
794 def revertToUnmodified(self): 808 def revertToUnmodified(self):
795 """ 809 """
796 Public slot to revert all changes. 810 Public slot to revert all changes.
797 """ 811 """
798 cleanIndex = self.__undoStack.cleanIndex() 812 cleanIndex = self.__undoStack.cleanIndex()
799 if cleanIndex >= 0: 813 if cleanIndex >= 0:
800 self.__undoStack.setIndex(cleanIndex) 814 self.__undoStack.setIndex(cleanIndex)
801 self.setCursorPosition(self.__chunks.pos() * 2) 815 self.setCursorPosition(self.__chunks.pos() * 2)
802 self.__refresh() 816 self.__refresh()
803 817
804 #################################################### 818 ####################################################
805 ## Cursor movement commands 819 ## Cursor movement commands
806 #################################################### 820 ####################################################
807 821
808 def moveCursorToNextChar(self): 822 def moveCursorToNextChar(self):
809 """ 823 """
810 Public method to move the cursor to the next byte. 824 Public method to move the cursor to the next byte.
811 """ 825 """
812 self.setCursorPosition(self.__cursorPosition + 1) 826 self.setCursorPosition(self.__cursorPosition + 1)
813 self.__resetSelection(self.__cursorPosition) 827 self.__resetSelection(self.__cursorPosition)
814 828
815 def moveCursorToPreviousChar(self): 829 def moveCursorToPreviousChar(self):
816 """ 830 """
817 Public method to move the cursor to the previous byte. 831 Public method to move the cursor to the previous byte.
818 """ 832 """
819 self.setCursorPosition(self.__cursorPosition - 1) 833 self.setCursorPosition(self.__cursorPosition - 1)
820 self.__resetSelection(self.__cursorPosition) 834 self.__resetSelection(self.__cursorPosition)
821 835
822 def moveCursorToEndOfLine(self): 836 def moveCursorToEndOfLine(self):
823 """ 837 """
824 Public method to move the cursor to the end of the current line. 838 Public method to move the cursor to the end of the current line.
825 """ 839 """
826 self.setCursorPosition(self.__cursorPosition | 840 self.setCursorPosition(self.__cursorPosition | (2 * self.BYTES_PER_LINE - 1))
827 (2 * self.BYTES_PER_LINE - 1))
828 self.__resetSelection(self.__cursorPosition) 841 self.__resetSelection(self.__cursorPosition)
829 842
830 def moveCursorToStartOfLine(self): 843 def moveCursorToStartOfLine(self):
831 """ 844 """
832 Public method to move the cursor to the beginning of the current line. 845 Public method to move the cursor to the beginning of the current line.
833 """ 846 """
834 self.setCursorPosition( 847 self.setCursorPosition(
835 self.__cursorPosition - 848 self.__cursorPosition - (self.__cursorPosition % (2 * self.BYTES_PER_LINE))
836 (self.__cursorPosition % (2 * self.BYTES_PER_LINE))) 849 )
837 self.__resetSelection(self.__cursorPosition) 850 self.__resetSelection(self.__cursorPosition)
838 851
839 def moveCursorToPreviousLine(self): 852 def moveCursorToPreviousLine(self):
840 """ 853 """
841 Public method to move the cursor to the previous line. 854 Public method to move the cursor to the previous line.
842 """ 855 """
843 self.setCursorPosition(self.__cursorPosition - 2 * self.BYTES_PER_LINE) 856 self.setCursorPosition(self.__cursorPosition - 2 * self.BYTES_PER_LINE)
844 self.__resetSelection(self.__cursorPosition) 857 self.__resetSelection(self.__cursorPosition)
845 858
846 def moveCursorToNextLine(self): 859 def moveCursorToNextLine(self):
847 """ 860 """
848 Public method to move the cursor to the next line. 861 Public method to move the cursor to the next line.
849 """ 862 """
850 self.setCursorPosition(self.__cursorPosition + 2 * self.BYTES_PER_LINE) 863 self.setCursorPosition(self.__cursorPosition + 2 * self.BYTES_PER_LINE)
851 self.__resetSelection(self.__cursorPosition) 864 self.__resetSelection(self.__cursorPosition)
852 865
853 def moveCursorToNextPage(self): 866 def moveCursorToNextPage(self):
854 """ 867 """
855 Public method to move the cursor to the next page. 868 Public method to move the cursor to the next page.
856 """ 869 """
857 self.setCursorPosition( 870 self.setCursorPosition(
858 self.__cursorPosition + 871 self.__cursorPosition + (self.__rowsShown - 1) * 2 * self.BYTES_PER_LINE
859 (self.__rowsShown - 1) * 2 * self.BYTES_PER_LINE) 872 )
860 self.__resetSelection(self.__cursorPosition) 873 self.__resetSelection(self.__cursorPosition)
861 874
862 def moveCursorToPreviousPage(self): 875 def moveCursorToPreviousPage(self):
863 """ 876 """
864 Public method to move the cursor to the previous page. 877 Public method to move the cursor to the previous page.
865 """ 878 """
866 self.setCursorPosition( 879 self.setCursorPosition(
867 self.__cursorPosition - 880 self.__cursorPosition - (self.__rowsShown - 1) * 2 * self.BYTES_PER_LINE
868 (self.__rowsShown - 1) * 2 * self.BYTES_PER_LINE) 881 )
869 self.__resetSelection(self.__cursorPosition) 882 self.__resetSelection(self.__cursorPosition)
870 883
871 def moveCursorToEndOfDocument(self): 884 def moveCursorToEndOfDocument(self):
872 """ 885 """
873 Public method to move the cursor to the end of the data. 886 Public method to move the cursor to the end of the data.
874 """ 887 """
875 self.setCursorPosition(self.__chunks.size() * 2) 888 self.setCursorPosition(self.__chunks.size() * 2)
876 self.__resetSelection(self.__cursorPosition) 889 self.__resetSelection(self.__cursorPosition)
877 890
878 def moveCursorToStartOfDocument(self): 891 def moveCursorToStartOfDocument(self):
879 """ 892 """
880 Public method to move the cursor to the start of the data. 893 Public method to move the cursor to the start of the data.
881 """ 894 """
882 self.setCursorPosition(0) 895 self.setCursorPosition(0)
883 self.__resetSelection(self.__cursorPosition) 896 self.__resetSelection(self.__cursorPosition)
884 897
885 #################################################### 898 ####################################################
886 ## Selection commands 899 ## Selection commands
887 #################################################### 900 ####################################################
888 901
889 def deselectAll(self): 902 def deselectAll(self):
890 """ 903 """
891 Public method to deselect all data. 904 Public method to deselect all data.
892 """ 905 """
893 self.__resetSelection(0) 906 self.__resetSelection(0)
894 self.__refresh() 907 self.__refresh()
895 908
896 def selectAll(self): 909 def selectAll(self):
897 """ 910 """
898 Public method to select all data. 911 Public method to select all data.
899 """ 912 """
900 self.__resetSelection(0) 913 self.__resetSelection(0)
901 self.__setSelection(2 * self.__chunks.size() + 1) 914 self.__setSelection(2 * self.__chunks.size() + 1)
902 self.__refresh() 915 self.__refresh()
903 916
904 def selectNextChar(self): 917 def selectNextChar(self):
905 """ 918 """
906 Public method to extend the selection by one byte right. 919 Public method to extend the selection by one byte right.
907 """ 920 """
908 pos = self.__cursorPosition + 1 921 pos = self.__cursorPosition + 1
909 self.setCursorPosition(pos) 922 self.setCursorPosition(pos)
910 self.__setSelection(pos) 923 self.__setSelection(pos)
911 924
912 def selectPreviousChar(self): 925 def selectPreviousChar(self):
913 """ 926 """
914 Public method to extend the selection by one byte left. 927 Public method to extend the selection by one byte left.
915 """ 928 """
916 pos = self.__cursorPosition - 1 929 pos = self.__cursorPosition - 1
917 self.setCursorPosition(pos) 930 self.setCursorPosition(pos)
918 self.__setSelection(pos) 931 self.__setSelection(pos)
919 932
920 def selectToEndOfLine(self): 933 def selectToEndOfLine(self):
921 """ 934 """
922 Public method to extend the selection to the end of line. 935 Public method to extend the selection to the end of line.
923 """ 936 """
924 pos = ( 937 pos = (
925 self.__cursorPosition - 938 self.__cursorPosition
926 (self.__cursorPosition % (2 * self.BYTES_PER_LINE)) + 939 - (self.__cursorPosition % (2 * self.BYTES_PER_LINE))
927 2 * self.BYTES_PER_LINE 940 + 2 * self.BYTES_PER_LINE
928 ) 941 )
929 self.setCursorPosition(pos) 942 self.setCursorPosition(pos)
930 self.__setSelection(pos) 943 self.__setSelection(pos)
931 944
932 def selectToStartOfLine(self): 945 def selectToStartOfLine(self):
933 """ 946 """
934 Public method to extend the selection to the start of line. 947 Public method to extend the selection to the start of line.
935 """ 948 """
936 pos = ( 949 pos = self.__cursorPosition - (
937 self.__cursorPosition - 950 self.__cursorPosition % (2 * self.BYTES_PER_LINE)
938 (self.__cursorPosition % (2 * self.BYTES_PER_LINE))
939 ) 951 )
940 self.setCursorPosition(pos) 952 self.setCursorPosition(pos)
941 self.__setSelection(pos) 953 self.__setSelection(pos)
942 954
943 def selectPreviousLine(self): 955 def selectPreviousLine(self):
944 """ 956 """
945 Public method to extend the selection one line up. 957 Public method to extend the selection one line up.
946 """ 958 """
947 pos = self.__cursorPosition - 2 * self.BYTES_PER_LINE 959 pos = self.__cursorPosition - 2 * self.BYTES_PER_LINE
948 self.setCursorPosition(pos) 960 self.setCursorPosition(pos)
949 self.__setSelection(pos) 961 self.__setSelection(pos)
950 962
951 def selectNextLine(self): 963 def selectNextLine(self):
952 """ 964 """
953 Public method to extend the selection one line down. 965 Public method to extend the selection one line down.
954 """ 966 """
955 pos = self.__cursorPosition + 2 * self.BYTES_PER_LINE 967 pos = self.__cursorPosition + 2 * self.BYTES_PER_LINE
956 self.setCursorPosition(pos) 968 self.setCursorPosition(pos)
957 self.__setSelection(pos) 969 self.__setSelection(pos)
958 970
959 def selectNextPage(self): 971 def selectNextPage(self):
960 """ 972 """
961 Public method to extend the selection one page down. 973 Public method to extend the selection one page down.
962 """ 974 """
963 pos = ( 975 pos = (
964 self.__cursorPosition + 976 self.__cursorPosition
965 ((self.viewport().height() // self.__pxCharHeight) - 1) * 977 + ((self.viewport().height() // self.__pxCharHeight) - 1)
966 2 * self.BYTES_PER_LINE 978 * 2
979 * self.BYTES_PER_LINE
967 ) 980 )
968 self.setCursorPosition(pos) 981 self.setCursorPosition(pos)
969 self.__setSelection(pos) 982 self.__setSelection(pos)
970 983
971 def selectPreviousPage(self): 984 def selectPreviousPage(self):
972 """ 985 """
973 Public method to extend the selection one page up. 986 Public method to extend the selection one page up.
974 """ 987 """
975 pos = ( 988 pos = (
976 self.__cursorPosition - 989 self.__cursorPosition
977 ((self.viewport().height() // self.__pxCharHeight) - 1) * 990 - ((self.viewport().height() // self.__pxCharHeight) - 1)
978 2 * self.BYTES_PER_LINE 991 * 2
992 * self.BYTES_PER_LINE
979 ) 993 )
980 self.setCursorPosition(pos) 994 self.setCursorPosition(pos)
981 self.__setSelection(pos) 995 self.__setSelection(pos)
982 996
983 def selectEndOfDocument(self): 997 def selectEndOfDocument(self):
984 """ 998 """
985 Public method to extend the selection to the end of the data. 999 Public method to extend the selection to the end of the data.
986 """ 1000 """
987 pos = self.__chunks.size() * 2 1001 pos = self.__chunks.size() * 2
988 self.setCursorPosition(pos) 1002 self.setCursorPosition(pos)
989 self.__setSelection(pos) 1003 self.__setSelection(pos)
990 1004
991 def selectStartOfDocument(self): 1005 def selectStartOfDocument(self):
992 """ 1006 """
993 Public method to extend the selection to the start of the data. 1007 Public method to extend the selection to the start of the data.
994 """ 1008 """
995 pos = 0 1009 pos = 0
996 self.setCursorPosition(pos) 1010 self.setCursorPosition(pos)
997 self.__setSelection(pos) 1011 self.__setSelection(pos)
998 1012
999 #################################################### 1013 ####################################################
1000 ## Edit commands 1014 ## Edit commands
1001 #################################################### 1015 ####################################################
1002 1016
1003 def cut(self): 1017 def cut(self):
1004 """ 1018 """
1005 Public method to cut the selected bytes and move them to the clipboard. 1019 Public method to cut the selected bytes and move them to the clipboard.
1006 """ 1020 """
1007 if not self.__readOnly: 1021 if not self.__readOnly:
1008 byteArray = self.__toHex(self.__chunks.data( 1022 byteArray = self.__toHex(
1009 self.getSelectionBegin(), self.getSelectionLength())) 1023 self.__chunks.data(self.getSelectionBegin(), self.getSelectionLength())
1024 )
1010 idx = 32 1025 idx = 32
1011 while idx < len(byteArray): 1026 while idx < len(byteArray):
1012 byteArray.insert(idx, "\n") 1027 byteArray.insert(idx, "\n")
1013 idx += 33 1028 idx += 33
1014 cb = QApplication.clipboard() 1029 cb = QApplication.clipboard()
1015 cb.setText(byteArray.decode(encoding="latin1")) 1030 cb.setText(byteArray.decode(encoding="latin1"))
1016 if self.__overwriteMode: 1031 if self.__overwriteMode:
1017 length = self.getSelectionLength() 1032 length = self.getSelectionLength()
1018 self.replaceByteArray(self.getSelectionBegin(), length, 1033 self.replaceByteArray(
1019 bytearray(length)) 1034 self.getSelectionBegin(), length, bytearray(length)
1035 )
1020 else: 1036 else:
1021 self.remove(self.getSelectionBegin(), 1037 self.remove(self.getSelectionBegin(), self.getSelectionLength())
1022 self.getSelectionLength())
1023 self.setCursorPosition(2 * self.getSelectionBegin()) 1038 self.setCursorPosition(2 * self.getSelectionBegin())
1024 self.__resetSelection(2 * self.getSelectionBegin()) 1039 self.__resetSelection(2 * self.getSelectionBegin())
1025 1040
1026 def copy(self): 1041 def copy(self):
1027 """ 1042 """
1028 Public method to copy the selected bytes to the clipboard. 1043 Public method to copy the selected bytes to the clipboard.
1029 """ 1044 """
1030 byteArray = self.__toHex(self.__chunks.data( 1045 byteArray = self.__toHex(
1031 self.getSelectionBegin(), self.getSelectionLength())) 1046 self.__chunks.data(self.getSelectionBegin(), self.getSelectionLength())
1047 )
1032 idx = 32 1048 idx = 32
1033 while idx < len(byteArray): 1049 while idx < len(byteArray):
1034 byteArray.insert(idx, "\n") 1050 byteArray.insert(idx, "\n")
1035 idx += 33 1051 idx += 33
1036 cb = QApplication.clipboard() 1052 cb = QApplication.clipboard()
1037 cb.setText(byteArray.decode(encoding="latin1")) 1053 cb.setText(byteArray.decode(encoding="latin1"))
1038 1054
1039 def paste(self): 1055 def paste(self):
1040 """ 1056 """
1041 Public method to paste bytes from the clipboard. 1057 Public method to paste bytes from the clipboard.
1042 """ 1058 """
1043 if not self.__readOnly: 1059 if not self.__readOnly:
1044 cb = QApplication.clipboard() 1060 cb = QApplication.clipboard()
1045 byteArray = self.__fromHex(cb.text().encode(encoding="latin1")) 1061 byteArray = self.__fromHex(cb.text().encode(encoding="latin1"))
1046 if self.__overwriteMode: 1062 if self.__overwriteMode:
1047 self.replaceByteArray(self.__bPosCurrent, len(byteArray), 1063 self.replaceByteArray(self.__bPosCurrent, len(byteArray), byteArray)
1048 byteArray)
1049 else: 1064 else:
1050 self.insertByteArray(self.__bPosCurrent, byteArray) 1065 self.insertByteArray(self.__bPosCurrent, byteArray)
1051 self.setCursorPosition( 1066 self.setCursorPosition(self.__cursorPosition + 2 * len(byteArray))
1052 self.__cursorPosition + 2 * len(byteArray))
1053 self.__resetSelection(2 * self.getSelectionBegin()) 1067 self.__resetSelection(2 * self.getSelectionBegin())
1054 1068
1055 def deleteByte(self): 1069 def deleteByte(self):
1056 """ 1070 """
1057 Public method to delete the current byte. 1071 Public method to delete the current byte.
1058 """ 1072 """
1059 if not self.__readOnly: 1073 if not self.__readOnly:
1060 if self.hasSelection(): 1074 if self.hasSelection():
1061 self.__bPosCurrent = self.getSelectionBegin() 1075 self.__bPosCurrent = self.getSelectionBegin()
1062 if self.__overwriteMode: 1076 if self.__overwriteMode:
1063 byteArray = bytearray(self.getSelectionLength()) 1077 byteArray = bytearray(self.getSelectionLength())
1064 self.replaceByteArray(self.__bPosCurrent, len(byteArray), 1078 self.replaceByteArray(self.__bPosCurrent, len(byteArray), byteArray)
1065 byteArray)
1066 else: 1079 else:
1067 self.remove(self.__bPosCurrent, 1080 self.remove(self.__bPosCurrent, self.getSelectionLength())
1068 self.getSelectionLength())
1069 else: 1081 else:
1070 if self.__overwriteMode: 1082 if self.__overwriteMode:
1071 self.replace(self.__bPosCurrent, 0) 1083 self.replace(self.__bPosCurrent, 0)
1072 else: 1084 else:
1073 self.remove(self.__bPosCurrent, 1) 1085 self.remove(self.__bPosCurrent, 1)
1074 self.setCursorPosition(2 * self.__bPosCurrent) 1086 self.setCursorPosition(2 * self.__bPosCurrent)
1075 self.__resetSelection(2 * self.__bPosCurrent) 1087 self.__resetSelection(2 * self.__bPosCurrent)
1076 1088
1077 def deleteByteBack(self): 1089 def deleteByteBack(self):
1078 """ 1090 """
1079 Public method to delete the previous byte. 1091 Public method to delete the previous byte.
1080 """ 1092 """
1081 if not self.__readOnly: 1093 if not self.__readOnly:
1082 if self.hasSelection(): 1094 if self.hasSelection():
1083 self.__bPosCurrent = self.getSelectionBegin() 1095 self.__bPosCurrent = self.getSelectionBegin()
1084 self.setCursorPosition(2 * self.__bPosCurrent) 1096 self.setCursorPosition(2 * self.__bPosCurrent)
1085 if self.__overwriteMode: 1097 if self.__overwriteMode:
1086 byteArray = bytearray(self.getSelectionLength()) 1098 byteArray = bytearray(self.getSelectionLength())
1087 self.replaceByteArray(self.__bPosCurrent, len(byteArray), 1099 self.replaceByteArray(self.__bPosCurrent, len(byteArray), byteArray)
1088 byteArray)
1089 else: 1100 else:
1090 self.remove(self.__bPosCurrent, 1101 self.remove(self.__bPosCurrent, self.getSelectionLength())
1091 self.getSelectionLength())
1092 else: 1102 else:
1093 self.__bPosCurrent -= 1 1103 self.__bPosCurrent -= 1
1094 if self.__overwriteMode: 1104 if self.__overwriteMode:
1095 self.replace(self.__bPosCurrent, 0) 1105 self.replace(self.__bPosCurrent, 0)
1096 else: 1106 else:
1097 self.remove(self.__bPosCurrent, 1) 1107 self.remove(self.__bPosCurrent, 1)
1098 self.setCursorPosition(2 * self.__bPosCurrent) 1108 self.setCursorPosition(2 * self.__bPosCurrent)
1099 self.__resetSelection(2 * self.__bPosCurrent) 1109 self.__resetSelection(2 * self.__bPosCurrent)
1100 1110
1101 #################################################### 1111 ####################################################
1102 ## Event handling methods 1112 ## Event handling methods
1103 #################################################### 1113 ####################################################
1104 1114
1105 def keyPressEvent(self, evt): 1115 def keyPressEvent(self, evt):
1106 """ 1116 """
1107 Protected method to handle key press events. 1117 Protected method to handle key press events.
1108 1118
1109 @param evt reference to the key event 1119 @param evt reference to the key event
1110 @type QKeyEvent 1120 @type QKeyEvent
1111 """ 1121 """
1112 # Cursor movements 1122 # Cursor movements
1113 if evt.matches(QKeySequence.StandardKey.MoveToNextChar): 1123 if evt.matches(QKeySequence.StandardKey.MoveToNextChar):
1128 self.moveCursorToPreviousPage() 1138 self.moveCursorToPreviousPage()
1129 elif evt.matches(QKeySequence.StandardKey.MoveToEndOfDocument): 1139 elif evt.matches(QKeySequence.StandardKey.MoveToEndOfDocument):
1130 self.moveCursorToEndOfDocument() 1140 self.moveCursorToEndOfDocument()
1131 elif evt.matches(QKeySequence.StandardKey.MoveToStartOfDocument): 1141 elif evt.matches(QKeySequence.StandardKey.MoveToStartOfDocument):
1132 self.moveCursorToStartOfDocument() 1142 self.moveCursorToStartOfDocument()
1133 1143
1134 # Selection commands 1144 # Selection commands
1135 elif evt.matches(QKeySequence.StandardKey.SelectAll): 1145 elif evt.matches(QKeySequence.StandardKey.SelectAll):
1136 self.selectAll() 1146 self.selectAll()
1137 elif evt.matches(QKeySequence.StandardKey.SelectNextChar): 1147 elif evt.matches(QKeySequence.StandardKey.SelectNextChar):
1138 self.selectNextChar() 1148 self.selectNextChar()
1152 self.selectPreviousPage() 1162 self.selectPreviousPage()
1153 elif evt.matches(QKeySequence.StandardKey.SelectEndOfDocument): 1163 elif evt.matches(QKeySequence.StandardKey.SelectEndOfDocument):
1154 self.selectEndOfDocument() 1164 self.selectEndOfDocument()
1155 elif evt.matches(QKeySequence.StandardKey.SelectStartOfDocument): 1165 elif evt.matches(QKeySequence.StandardKey.SelectStartOfDocument):
1156 self.selectStartOfDocument() 1166 self.selectStartOfDocument()
1157 1167
1158 # Edit commands 1168 # Edit commands
1159 elif evt.matches(QKeySequence.StandardKey.Copy): 1169 elif evt.matches(QKeySequence.StandardKey.Copy):
1160 self.copy() 1170 self.copy()
1161 elif ( 1171 elif (
1162 evt.key() == Qt.Key.Key_Insert and 1172 evt.key() == Qt.Key.Key_Insert
1163 evt.modifiers() == Qt.KeyboardModifier.NoModifier 1173 and evt.modifiers() == Qt.KeyboardModifier.NoModifier
1164 ): 1174 ):
1165 self.setOverwriteMode(not self.overwriteMode()) 1175 self.setOverwriteMode(not self.overwriteMode())
1166 self.setCursorPosition(self.__cursorPosition) 1176 self.setCursorPosition(self.__cursorPosition)
1167 1177
1168 elif not self.__readOnly: 1178 elif not self.__readOnly:
1169 if evt.matches(QKeySequence.StandardKey.Cut): 1179 if evt.matches(QKeySequence.StandardKey.Cut):
1170 self.cut() 1180 self.cut()
1171 elif evt.matches(QKeySequence.StandardKey.Paste): 1181 elif evt.matches(QKeySequence.StandardKey.Paste):
1172 self.paste() 1182 self.paste()
1173 elif evt.matches(QKeySequence.StandardKey.Delete): 1183 elif evt.matches(QKeySequence.StandardKey.Delete):
1174 self.deleteByte() 1184 self.deleteByte()
1175 elif ( 1185 elif (
1176 evt.key() == Qt.Key.Key_Backspace and 1186 evt.key() == Qt.Key.Key_Backspace
1177 evt.modifiers() == Qt.KeyboardModifier.NoModifier 1187 and evt.modifiers() == Qt.KeyboardModifier.NoModifier
1178 ): 1188 ):
1179 self.deleteByteBack() 1189 self.deleteByteBack()
1180 elif evt.matches(QKeySequence.StandardKey.Undo): 1190 elif evt.matches(QKeySequence.StandardKey.Undo):
1181 self.undo() 1191 self.undo()
1182 elif evt.matches(QKeySequence.StandardKey.Redo): 1192 elif evt.matches(QKeySequence.StandardKey.Redo):
1183 self.redo() 1193 self.redo()
1184 1194
1185 elif QApplication.keyboardModifiers() in [ 1195 elif QApplication.keyboardModifiers() in [
1186 Qt.KeyboardModifier.NoModifier, 1196 Qt.KeyboardModifier.NoModifier,
1187 Qt.KeyboardModifier.KeypadModifier 1197 Qt.KeyboardModifier.KeypadModifier,
1188 ]: 1198 ]:
1189 # some hex input 1199 # some hex input
1190 key = evt.text() 1200 key = evt.text()
1191 if key and key in "0123456789abcdef": 1201 if key and key in "0123456789abcdef":
1192 if self.hasSelection(): 1202 if self.hasSelection():
1193 if self.__overwriteMode: 1203 if self.__overwriteMode:
1194 length = self.getSelectionLength() 1204 length = self.getSelectionLength()
1195 self.replaceByteArray( 1205 self.replaceByteArray(
1196 self.getSelectionBegin(), length, 1206 self.getSelectionBegin(), length, bytearray(length)
1197 bytearray(length)) 1207 )
1198 else: 1208 else:
1199 self.remove(self.getSelectionBegin(), 1209 self.remove(
1200 self.getSelectionLength()) 1210 self.getSelectionBegin(), self.getSelectionLength()
1211 )
1201 self.__bPosCurrent = self.getSelectionBegin() 1212 self.__bPosCurrent = self.getSelectionBegin()
1202 self.setCursorPosition(2 * self.__bPosCurrent) 1213 self.setCursorPosition(2 * self.__bPosCurrent)
1203 self.__resetSelection(2 * self.__bPosCurrent) 1214 self.__resetSelection(2 * self.__bPosCurrent)
1204 1215
1205 # if in insert mode, insert a byte 1216 # if in insert mode, insert a byte
1206 if ( 1217 if not self.__overwriteMode and (self.__cursorPosition % 2) == 0:
1207 not self.__overwriteMode and
1208 (self.__cursorPosition % 2) == 0
1209 ):
1210 self.insert(self.__bPosCurrent, 0) 1218 self.insert(self.__bPosCurrent, 0)
1211 1219
1212 # change content 1220 # change content
1213 if self.__chunks.size() > 0: 1221 if self.__chunks.size() > 0:
1214 hexValue = self.__toHex( 1222 hexValue = self.__toHex(
1215 self.__chunks.data(self.__bPosCurrent, 1)) 1223 self.__chunks.data(self.__bPosCurrent, 1)
1224 )
1216 if (self.__cursorPosition % 2) == 0: 1225 if (self.__cursorPosition % 2) == 0:
1217 hexValue[0] = ord(key) 1226 hexValue[0] = ord(key)
1218 else: 1227 else:
1219 hexValue[1] = ord(key) 1228 hexValue[1] = ord(key)
1220 self.replace(self.__bPosCurrent, 1229 self.replace(self.__bPosCurrent, self.__fromHex(hexValue)[0])
1221 self.__fromHex(hexValue)[0]) 1230
1222
1223 self.setCursorPosition(self.__cursorPosition + 1) 1231 self.setCursorPosition(self.__cursorPosition + 1)
1224 self.__resetSelection(self.__cursorPosition) 1232 self.__resetSelection(self.__cursorPosition)
1225 else: 1233 else:
1226 return 1234 return
1227 else: 1235 else:
1228 return 1236 return
1229 else: 1237 else:
1230 return 1238 return
1231 else: 1239 else:
1232 return 1240 return
1233 1241
1234 self.__refresh() 1242 self.__refresh()
1235 1243
1236 def mouseMoveEvent(self, evt): 1244 def mouseMoveEvent(self, evt):
1237 """ 1245 """
1238 Protected method to handle mouse moves. 1246 Protected method to handle mouse moves.
1239 1247
1240 @param evt reference to the mouse event 1248 @param evt reference to the mouse event
1241 @type QMouseEvent 1249 @type QMouseEvent
1242 """ 1250 """
1243 self.__blink = False 1251 self.__blink = False
1244 self.viewport().update() 1252 self.viewport().update()
1245 actPos = self.cursorPositionFromPoint(evt.position().toPoint()) 1253 actPos = self.cursorPositionFromPoint(evt.position().toPoint())
1246 if actPos >= 0: 1254 if actPos >= 0:
1247 self.setCursorPosition(actPos) 1255 self.setCursorPosition(actPos)
1248 self.__setSelection(actPos) 1256 self.__setSelection(actPos)
1249 1257
1250 def mousePressEvent(self, evt): 1258 def mousePressEvent(self, evt):
1251 """ 1259 """
1252 Protected method to handle mouse button presses. 1260 Protected method to handle mouse button presses.
1253 1261
1254 @param evt reference to the mouse event 1262 @param evt reference to the mouse event
1255 @type QMouseEvent 1263 @type QMouseEvent
1256 """ 1264 """
1257 self.__blink = False 1265 self.__blink = False
1258 self.viewport().update() 1266 self.viewport().update()
1261 if evt.modifiers() == Qt.KeyboardModifier.ShiftModifier: 1269 if evt.modifiers() == Qt.KeyboardModifier.ShiftModifier:
1262 self.__setSelection(cPos) 1270 self.__setSelection(cPos)
1263 else: 1271 else:
1264 self.__resetSelection(cPos) 1272 self.__resetSelection(cPos)
1265 self.setCursorPosition(cPos) 1273 self.setCursorPosition(cPos)
1266 1274
1267 def paintEvent(self, evt): 1275 def paintEvent(self, evt):
1268 """ 1276 """
1269 Protected method to handle paint events. 1277 Protected method to handle paint events.
1270 1278
1271 @param evt reference to the paint event 1279 @param evt reference to the paint event
1272 @type QPaintEvent 1280 @type QPaintEvent
1273 """ 1281 """
1274 painter = QPainter(self.viewport()) 1282 painter = QPainter(self.viewport())
1275 1283
1276 # initialize colors 1284 # initialize colors
1277 if ericApp().usesDarkPalette(): 1285 if ericApp().usesDarkPalette():
1278 addressAreaForeground = self.palette().color( 1286 addressAreaForeground = self.palette().color(QPalette.ColorRole.Text)
1279 QPalette.ColorRole.Text) 1287 addressAreaBackground = (
1280 addressAreaBackground = self.palette().color( 1288 self.palette().color(QPalette.ColorRole.Base).lighter(200)
1281 QPalette.ColorRole.Base).lighter(200) 1289 )
1282 highlightingForeground = self.palette().color( 1290 highlightingForeground = (
1283 QPalette.ColorRole.HighlightedText).darker(200) 1291 self.palette().color(QPalette.ColorRole.HighlightedText).darker(200)
1284 highlightingBackground = self.palette().color( 1292 )
1285 QPalette.ColorRole.Highlight).lighter() 1293 highlightingBackground = (
1294 self.palette().color(QPalette.ColorRole.Highlight).lighter()
1295 )
1286 else: 1296 else:
1287 addressAreaForeground = self.palette().color( 1297 addressAreaForeground = self.palette().color(QPalette.ColorRole.Text)
1288 QPalette.ColorRole.Text) 1298 addressAreaBackground = (
1289 addressAreaBackground = self.palette().color( 1299 self.palette().color(QPalette.ColorRole.Base).darker()
1290 QPalette.ColorRole.Base).darker() 1300 )
1291 highlightingForeground = self.palette().color( 1301 highlightingForeground = (
1292 QPalette.ColorRole.HighlightedText).lighter() 1302 self.palette().color(QPalette.ColorRole.HighlightedText).lighter()
1293 highlightingBackground = self.palette().color( 1303 )
1294 QPalette.ColorRole.Highlight).darker() 1304 highlightingBackground = (
1295 selectionForeground = self.palette().color( 1305 self.palette().color(QPalette.ColorRole.Highlight).darker()
1296 QPalette.ColorRole.HighlightedText) 1306 )
1297 selectionBackground = self.palette().color( 1307 selectionForeground = self.palette().color(QPalette.ColorRole.HighlightedText)
1298 QPalette.ColorRole.Highlight) 1308 selectionBackground = self.palette().color(QPalette.ColorRole.Highlight)
1299 standardBackground = self.viewport().palette().color( 1309 standardBackground = self.viewport().palette().color(QPalette.ColorRole.Base)
1300 QPalette.ColorRole.Base) 1310 standardForeground = self.viewport().palette().color(QPalette.ColorRole.Text)
1301 standardForeground = self.viewport().palette().color( 1311
1302 QPalette.ColorRole.Text) 1312 if evt.rect() != self.__cursorRect and evt.rect() != self.__cursorRectAscii:
1303
1304 if (
1305 evt.rect() != self.__cursorRect and
1306 evt.rect() != self.__cursorRectAscii
1307 ):
1308 pxOfsX = self.horizontalScrollBar().value() 1313 pxOfsX = self.horizontalScrollBar().value()
1309 pxPosStartY = self.__pxCharHeight 1314 pxPosStartY = self.__pxCharHeight
1310 1315
1311 # draw some patterns if needed 1316 # draw some patterns if needed
1312 painter.fillRect(evt.rect(), standardBackground) 1317 painter.fillRect(evt.rect(), standardBackground)
1313 if self.__addressArea: 1318 if self.__addressArea:
1314 painter.fillRect( 1319 painter.fillRect(
1315 QRect(-pxOfsX, evt.rect().top(), 1320 QRect(
1316 self.__pxPosHexX - self.__pxGapAdrHex // 2 - pxOfsX, 1321 -pxOfsX,
1317 self.height()), 1322 evt.rect().top(),
1318 addressAreaBackground) 1323 self.__pxPosHexX - self.__pxGapAdrHex // 2 - pxOfsX,
1324 self.height(),
1325 ),
1326 addressAreaBackground,
1327 )
1319 if self.__asciiArea: 1328 if self.__asciiArea:
1320 linePos = self.__pxPosAsciiX - (self.__pxGapHexAscii // 2) 1329 linePos = self.__pxPosAsciiX - (self.__pxGapHexAscii // 2)
1321 painter.setPen(Qt.GlobalColor.gray) 1330 painter.setPen(Qt.GlobalColor.gray)
1322 painter.drawLine(linePos - pxOfsX, evt.rect().top(), 1331 painter.drawLine(
1323 linePos - pxOfsX, self.height()) 1332 linePos - pxOfsX, evt.rect().top(), linePos - pxOfsX, self.height()
1324 1333 )
1334
1325 # paint the address area 1335 # paint the address area
1326 if self.__addressArea: 1336 if self.__addressArea:
1327 painter.setPen(addressAreaForeground) 1337 painter.setPen(addressAreaForeground)
1328 address = "" 1338 address = ""
1329 row = 0 1339 row = 0
1330 pxPosY = self.__pxCharHeight 1340 pxPosY = self.__pxCharHeight
1331 while row <= len(self.__dataShown) // self.BYTES_PER_LINE: 1341 while row <= len(self.__dataShown) // self.BYTES_PER_LINE:
1332 address = "{0:0{1}x}".format( 1342 address = "{0:0{1}x}".format(
1333 self.__bPosFirst + row * self.BYTES_PER_LINE, 1343 self.__bPosFirst + row * self.BYTES_PER_LINE, self.__addrDigits
1334 self.__addrDigits) 1344 )
1335 address = Globals.strGroup(address, ":", 4) 1345 address = Globals.strGroup(address, ":", 4)
1336 painter.drawText(self.__pxPosAdrX - pxOfsX, pxPosY, 1346 painter.drawText(self.__pxPosAdrX - pxOfsX, pxPosY, address)
1337 address)
1338 # increment loop variables 1347 # increment loop variables
1339 row += 1 1348 row += 1
1340 pxPosY += self.__pxCharHeight 1349 pxPosY += self.__pxCharHeight
1341 1350
1342 # paint hex and ascii area 1351 # paint hex and ascii area
1343 painter.setBackgroundMode(Qt.BGMode.TransparentMode) 1352 painter.setBackgroundMode(Qt.BGMode.TransparentMode)
1344 1353
1345 row = 0 1354 row = 0
1346 pxPosY = pxPosStartY 1355 pxPosY = pxPosStartY
1347 while row <= self.__rowsShown: 1356 while row <= self.__rowsShown:
1348 pxPosX = self.__pxPosHexX - pxOfsX 1357 pxPosX = self.__pxPosHexX - pxOfsX
1349 pxPosAsciiX2 = self.__pxPosAsciiX - pxOfsX 1358 pxPosAsciiX2 = self.__pxPosAsciiX - pxOfsX
1350 bPosLine = row * self.BYTES_PER_LINE 1359 bPosLine = row * self.BYTES_PER_LINE
1351 1360
1352 colIdx = 0 1361 colIdx = 0
1353 while ( 1362 while (
1354 bPosLine + colIdx < len(self.__dataShown) and 1363 bPosLine + colIdx < len(self.__dataShown)
1355 colIdx < self.BYTES_PER_LINE 1364 and colIdx < self.BYTES_PER_LINE
1356 ): 1365 ):
1357 background = standardBackground 1366 background = standardBackground
1358 painter.setPen(standardForeground) 1367 painter.setPen(standardForeground)
1359 1368
1360 posBa = self.__bPosFirst + bPosLine + colIdx 1369 posBa = self.__bPosFirst + bPosLine + colIdx
1361 if ( 1370 if (
1362 self.getSelectionBegin() <= posBa and 1371 self.getSelectionBegin() <= posBa
1363 self.getSelectionEnd() > posBa 1372 and self.getSelectionEnd() > posBa
1364 ): 1373 ):
1365 background = selectionBackground 1374 background = selectionBackground
1366 painter.setPen(selectionForeground) 1375 painter.setPen(selectionForeground)
1367 elif ( 1376 elif (
1368 self.__highlighting and 1377 self.__highlighting
1369 self.__markedShown and 1378 and self.__markedShown
1370 self.__markedShown[posBa - self.__bPosFirst] 1379 and self.__markedShown[posBa - self.__bPosFirst]
1371 ): 1380 ):
1372 background = highlightingBackground 1381 background = highlightingBackground
1373 painter.setPen(highlightingForeground) 1382 painter.setPen(highlightingForeground)
1374 1383
1375 # render hex value 1384 # render hex value
1376 rect = QRect() 1385 rect = QRect()
1377 if colIdx == 0: 1386 if colIdx == 0:
1378 rect.setRect( 1387 rect.setRect(
1379 pxPosX, 1388 pxPosX,
1380 pxPosY - self.__pxCharHeight + 1389 pxPosY - self.__pxCharHeight + self.__pxSelectionSub,
1381 self.__pxSelectionSub,
1382 2 * self.__pxCharWidth, 1390 2 * self.__pxCharWidth,
1383 self.__pxCharHeight) 1391 self.__pxCharHeight,
1392 )
1384 else: 1393 else:
1385 rect.setRect( 1394 rect.setRect(
1386 pxPosX - self.__pxCharWidth, 1395 pxPosX - self.__pxCharWidth,
1387 pxPosY - self.__pxCharHeight + 1396 pxPosY - self.__pxCharHeight + self.__pxSelectionSub,
1388 self.__pxSelectionSub,
1389 3 * self.__pxCharWidth, 1397 3 * self.__pxCharWidth,
1390 self.__pxCharHeight) 1398 self.__pxCharHeight,
1399 )
1391 painter.fillRect(rect, background) 1400 painter.fillRect(rect, background)
1392 hexStr = ( 1401 hexStr = chr(self.__hexDataShown[(bPosLine + colIdx) * 2]) + chr(
1393 chr(self.__hexDataShown[(bPosLine + colIdx) * 2]) + 1402 self.__hexDataShown[(bPosLine + colIdx) * 2 + 1]
1394 chr(self.__hexDataShown[(bPosLine + colIdx) * 2 + 1])
1395 ) 1403 )
1396 painter.drawText(pxPosX, pxPosY, hexStr) 1404 painter.drawText(pxPosX, pxPosY, hexStr)
1397 pxPosX += 3 * self.__pxCharWidth 1405 pxPosX += 3 * self.__pxCharWidth
1398 1406
1399 # render ascii value 1407 # render ascii value
1400 if self.__asciiArea: 1408 if self.__asciiArea:
1401 by = self.__dataShown[bPosLine + colIdx] 1409 by = self.__dataShown[bPosLine + colIdx]
1402 if by < 0x20 or (by > 0x7e and by < 0xa0): 1410 if by < 0x20 or (by > 0x7E and by < 0xA0):
1403 ch = "." 1411 ch = "."
1404 else: 1412 else:
1405 ch = chr(by) 1413 ch = chr(by)
1406 rect.setRect( 1414 rect.setRect(
1407 pxPosAsciiX2, 1415 pxPosAsciiX2,
1408 pxPosY - self.__pxCharHeight + 1416 pxPosY - self.__pxCharHeight + self.__pxSelectionSub,
1409 self.__pxSelectionSub,
1410 self.__pxCharWidth, 1417 self.__pxCharWidth,
1411 self.__pxCharHeight) 1418 self.__pxCharHeight,
1419 )
1412 painter.fillRect(rect, background) 1420 painter.fillRect(rect, background)
1413 painter.drawText(pxPosAsciiX2, pxPosY, ch) 1421 painter.drawText(pxPosAsciiX2, pxPosY, ch)
1414 pxPosAsciiX2 += self.__pxCharWidth 1422 pxPosAsciiX2 += self.__pxCharWidth
1415 1423
1416 # increment loop variable 1424 # increment loop variable
1417 colIdx += 1 1425 colIdx += 1
1418 1426
1419 # increment loop variables 1427 # increment loop variables
1420 row += 1 1428 row += 1
1421 pxPosY += self.__pxCharHeight 1429 pxPosY += self.__pxCharHeight
1422 1430
1423 painter.setBackgroundMode(Qt.BGMode.TransparentMode) 1431 painter.setBackgroundMode(Qt.BGMode.TransparentMode)
1424 painter.setPen(standardForeground) 1432 painter.setPen(standardForeground)
1425 1433
1426 # paint cursor 1434 # paint cursor
1427 if self.__blink and not self.__readOnly and self.isActiveWindow(): 1435 if self.__blink and not self.__readOnly and self.isActiveWindow():
1428 painter.fillRect(self.__cursorRect, standardForeground) 1436 painter.fillRect(self.__cursorRect, standardForeground)
1429 else: 1437 else:
1430 if self.__hexDataShown: 1438 if self.__hexDataShown:
1431 try: 1439 try:
1432 c = chr(self.__hexDataShown[ 1440 c = chr(
1433 self.__cursorPosition - self.__bPosFirst * 2]) 1441 self.__hexDataShown[
1442 self.__cursorPosition - self.__bPosFirst * 2
1443 ]
1444 )
1434 except IndexError: 1445 except IndexError:
1435 c = "" 1446 c = ""
1436 else: 1447 else:
1437 c = "" 1448 c = ""
1438 painter.drawText(self.__pxCursorX, self.__pxCursorY, c) 1449 painter.drawText(self.__pxCursorX, self.__pxCursorY, c)
1439 1450
1440 if self.__asciiArea: 1451 if self.__asciiArea:
1441 painter.drawRect(self.__cursorRectAscii) 1452 painter.drawRect(self.__cursorRectAscii)
1442 1453
1443 # emit event, if size has changed 1454 # emit event, if size has changed
1444 if self.__lastEventSize != self.__chunks.size(): 1455 if self.__lastEventSize != self.__chunks.size():
1445 self.__lastEventSize = self.__chunks.size() 1456 self.__lastEventSize = self.__chunks.size()
1446 self.currentSizeChanged.emit(self.__lastEventSize) 1457 self.currentSizeChanged.emit(self.__lastEventSize)
1447 1458
1448 def resizeEvent(self, evt): 1459 def resizeEvent(self, evt):
1449 """ 1460 """
1450 Protected method to handle resize events. 1461 Protected method to handle resize events.
1451 1462
1452 @param evt reference to the resize event 1463 @param evt reference to the resize event
1453 @type QResizeEvent 1464 @type QResizeEvent
1454 """ 1465 """
1455 self.__adjust() 1466 self.__adjust()
1456 1467
1457 def __resetSelection(self, pos=None): 1468 def __resetSelection(self, pos=None):
1458 """ 1469 """
1459 Private method to reset the selection. 1470 Private method to reset the selection.
1460 1471
1461 @param pos position to set selection start and end to 1472 @param pos position to set selection start and end to
1462 (if this is None, selection end is set to selection start) 1473 (if this is None, selection end is set to selection start)
1463 @type int or None 1474 @type int or None
1464 """ 1475 """
1465 if pos is None: 1476 if pos is None:
1470 pos = 0 1481 pos = 0
1471 pos //= 2 1482 pos //= 2
1472 self.__bSelectionInit = pos 1483 self.__bSelectionInit = pos
1473 self.__bSelectionBegin = pos 1484 self.__bSelectionBegin = pos
1474 self.__bSelectionEnd = pos 1485 self.__bSelectionEnd = pos
1475 1486
1476 self.selectionAvailable.emit(False) 1487 self.selectionAvailable.emit(False)
1477 1488
1478 def __setSelection(self, pos): 1489 def __setSelection(self, pos):
1479 """ 1490 """
1480 Private method to set the selection. 1491 Private method to set the selection.
1481 1492
1482 @param pos position 1493 @param pos position
1483 @type int 1494 @type int
1484 """ 1495 """
1485 if pos < 0: 1496 if pos < 0:
1486 pos = 0 1497 pos = 0
1489 self.__bSelectionEnd = pos 1500 self.__bSelectionEnd = pos
1490 self.__bSelectionBegin = self.__bSelectionInit 1501 self.__bSelectionBegin = self.__bSelectionInit
1491 else: 1502 else:
1492 self.__bSelectionBegin = pos 1503 self.__bSelectionBegin = pos
1493 self.__bSelectionEnd = self.__bSelectionInit 1504 self.__bSelectionEnd = self.__bSelectionInit
1494 1505
1495 self.selectionAvailable.emit(True) 1506 self.selectionAvailable.emit(True)
1496 1507
1497 def getSelectionBegin(self): 1508 def getSelectionBegin(self):
1498 """ 1509 """
1499 Public method to get the start of the selection. 1510 Public method to get the start of the selection.
1500 1511
1501 @return selection start 1512 @return selection start
1502 @rtype int 1513 @rtype int
1503 """ 1514 """
1504 return self.__bSelectionBegin 1515 return self.__bSelectionBegin
1505 1516
1506 def getSelectionEnd(self): 1517 def getSelectionEnd(self):
1507 """ 1518 """
1508 Public method to get the end of the selection. 1519 Public method to get the end of the selection.
1509 1520
1510 @return selection end 1521 @return selection end
1511 @rtype int 1522 @rtype int
1512 """ 1523 """
1513 return self.__bSelectionEnd 1524 return self.__bSelectionEnd
1514 1525
1515 def getSelectionLength(self): 1526 def getSelectionLength(self):
1516 """ 1527 """
1517 Public method to get the length of the selection. 1528 Public method to get the length of the selection.
1518 1529
1519 @return selection length 1530 @return selection length
1520 @rtype int 1531 @rtype int
1521 """ 1532 """
1522 return self.__bSelectionEnd - self.__bSelectionBegin 1533 return self.__bSelectionEnd - self.__bSelectionBegin
1523 1534
1524 def hasSelection(self): 1535 def hasSelection(self):
1525 """ 1536 """
1526 Public method to test for a selection. 1537 Public method to test for a selection.
1527 1538
1528 @return flag indicating the presence of a selection 1539 @return flag indicating the presence of a selection
1529 @rtype bool 1540 @rtype bool
1530 """ 1541 """
1531 return self.__bSelectionBegin != self.__bSelectionEnd 1542 return self.__bSelectionBegin != self.__bSelectionEnd
1532 1543
1533 def __initialize(self): 1544 def __initialize(self):
1534 """ 1545 """
1535 Private method to do some initialization. 1546 Private method to do some initialization.
1536 """ 1547 """
1537 self.__undoStack.clear() 1548 self.__undoStack.clear()
1538 self.setAddressOffset(0) 1549 self.setAddressOffset(0)
1539 self.__resetSelection(0) 1550 self.__resetSelection(0)
1540 self.setCursorPosition(0) 1551 self.setCursorPosition(0)
1541 self.verticalScrollBar().setValue(0) 1552 self.verticalScrollBar().setValue(0)
1542 self.__modified = False 1553 self.__modified = False
1543 1554
1544 def __readBuffers(self): 1555 def __readBuffers(self):
1545 """ 1556 """
1546 Private method to read the buffers. 1557 Private method to read the buffers.
1547 """ 1558 """
1548 self.__dataShown = self.__chunks.data( 1559 self.__dataShown = self.__chunks.data(
1549 self.__bPosFirst, 1560 self.__bPosFirst,
1550 self.__bPosLast - self.__bPosFirst + self.BYTES_PER_LINE + 1, 1561 self.__bPosLast - self.__bPosFirst + self.BYTES_PER_LINE + 1,
1551 self.__markedShown 1562 self.__markedShown,
1552 ) 1563 )
1553 self.__hexDataShown = self.__toHex(self.__dataShown) 1564 self.__hexDataShown = self.__toHex(self.__dataShown)
1554 1565
1555 def __toHex(self, byteArray): 1566 def __toHex(self, byteArray):
1556 """ 1567 """
1557 Private method to convert the data of a Python bytearray to hex. 1568 Private method to convert the data of a Python bytearray to hex.
1558 1569
1559 @param byteArray byte array to be converted 1570 @param byteArray byte array to be converted
1560 @type bytearray 1571 @type bytearray
1561 @return converted data 1572 @return converted data
1562 @rtype bytearray 1573 @rtype bytearray
1563 """ 1574 """
1564 return bytearray(QByteArray(byteArray).toHex()) 1575 return bytearray(QByteArray(byteArray).toHex())
1565 1576
1566 def __fromHex(self, byteArray): 1577 def __fromHex(self, byteArray):
1567 """ 1578 """
1568 Private method to convert data of a Python bytearray from hex. 1579 Private method to convert data of a Python bytearray from hex.
1569 1580
1570 @param byteArray byte array to be converted 1581 @param byteArray byte array to be converted
1571 @type bytearray 1582 @type bytearray
1572 @return converted data 1583 @return converted data
1573 @rtype bytearray 1584 @rtype bytearray
1574 """ 1585 """
1575 return bytearray(QByteArray.fromHex(byteArray)) 1586 return bytearray(QByteArray.fromHex(byteArray))
1576 1587
1577 def __toReadable(self, byteArray): 1588 def __toReadable(self, byteArray):
1578 """ 1589 """
1579 Private method to convert some data into a readable format. 1590 Private method to convert some data into a readable format.
1580 1591
1581 @param byteArray data to be converted 1592 @param byteArray data to be converted
1582 @type bytearray or QByteArray 1593 @type bytearray or QByteArray
1583 @return readable data 1594 @return readable data
1584 @rtype str 1595 @rtype str
1585 """ 1596 """
1586 byteArray = bytearray(byteArray) 1597 byteArray = bytearray(byteArray)
1587 result = "" 1598 result = ""
1588 for i in range(0, len(byteArray), 16): 1599 for i in range(0, len(byteArray), 16):
1589 addrStr = "{0:0{1}x}".format(self.__addressOffset + i, 1600 addrStr = "{0:0{1}x}".format(self.__addressOffset + i, self.addressWidth())
1590 self.addressWidth())
1591 hexStr = "" 1601 hexStr = ""
1592 ascStr = "" 1602 ascStr = ""
1593 for j in range(16): 1603 for j in range(16):
1594 if (i + j) < len(byteArray): 1604 if (i + j) < len(byteArray):
1595 hexStr += " {0:02x}".format(byteArray[i + j]) 1605 hexStr += " {0:02x}".format(byteArray[i + j])
1596 by = byteArray[i + j] 1606 by = byteArray[i + j]
1597 if by < 0x20 or (by > 0x7e and by < 0xa0): 1607 if by < 0x20 or (by > 0x7E and by < 0xA0):
1598 ch = "." 1608 ch = "."
1599 else: 1609 else:
1600 ch = chr(by) 1610 ch = chr(by)
1601 ascStr += ch 1611 ascStr += ch
1602 result += "{0} {1:<48} {2:<17}\n".format(addrStr, hexStr, ascStr) 1612 result += "{0} {1:<48} {2:<17}\n".format(addrStr, hexStr, ascStr)
1603 return result 1613 return result
1604 1614
1605 @pyqtSlot() 1615 @pyqtSlot()
1606 def __adjust(self): 1616 def __adjust(self):
1607 """ 1617 """
1608 Private slot to recalculate pixel positions. 1618 Private slot to recalculate pixel positions.
1609 """ 1619 """
1610 # recalculate graphics 1620 # recalculate graphics
1611 if self.__addressArea: 1621 if self.__addressArea:
1612 self.__addrDigits = self.addressWidth() 1622 self.__addrDigits = self.addressWidth()
1613 self.__addrSeparators = self.__addrDigits // 4 - 1 1623 self.__addrSeparators = self.__addrDigits // 4 - 1
1614 self.__pxPosHexX = ( 1624 self.__pxPosHexX = (
1615 self.__pxGapAdr + 1625 self.__pxGapAdr
1616 (self.__addrDigits + self.__addrSeparators) * 1626 + (self.__addrDigits + self.__addrSeparators) * self.__pxCharWidth
1617 self.__pxCharWidth + self.__pxGapAdrHex) 1627 + self.__pxGapAdrHex
1628 )
1618 else: 1629 else:
1619 self.__pxPosHexX = self.__pxGapAdrHex 1630 self.__pxPosHexX = self.__pxGapAdrHex
1620 self.__pxPosAdrX = self.__pxGapAdr 1631 self.__pxPosAdrX = self.__pxGapAdr
1621 self.__pxPosAsciiX = ( 1632 self.__pxPosAsciiX = (
1622 self.__pxPosHexX + 1633 self.__pxPosHexX
1623 self.HEXCHARS_PER_LINE * self.__pxCharWidth + 1634 + self.HEXCHARS_PER_LINE * self.__pxCharWidth
1624 self.__pxGapHexAscii 1635 + self.__pxGapHexAscii
1625 ) 1636 )
1626 1637
1627 # set horizontal scrollbar 1638 # set horizontal scrollbar
1628 pxWidth = self.__pxPosAsciiX 1639 pxWidth = self.__pxPosAsciiX
1629 if self.__asciiArea: 1640 if self.__asciiArea:
1630 pxWidth += self.BYTES_PER_LINE * self.__pxCharWidth 1641 pxWidth += self.BYTES_PER_LINE * self.__pxCharWidth
1631 self.horizontalScrollBar().setRange( 1642 self.horizontalScrollBar().setRange(0, pxWidth - self.viewport().width())
1632 0, pxWidth - self.viewport().width())
1633 self.horizontalScrollBar().setPageStep(self.viewport().width()) 1643 self.horizontalScrollBar().setPageStep(self.viewport().width())
1634 1644
1635 # set vertical scrollbar 1645 # set vertical scrollbar
1636 self.__rowsShown = ( 1646 self.__rowsShown = (self.viewport().height() - 4) // self.__pxCharHeight
1637 (self.viewport().height() - 4) // self.__pxCharHeight
1638 )
1639 lineCount = (self.__chunks.size() // self.BYTES_PER_LINE) + 1 1647 lineCount = (self.__chunks.size() // self.BYTES_PER_LINE) + 1
1640 self.verticalScrollBar().setRange(0, lineCount - self.__rowsShown) 1648 self.verticalScrollBar().setRange(0, lineCount - self.__rowsShown)
1641 self.verticalScrollBar().setPageStep(self.__rowsShown) 1649 self.verticalScrollBar().setPageStep(self.__rowsShown)
1642 1650
1643 # do the rest 1651 # do the rest
1644 value = self.verticalScrollBar().value() 1652 value = self.verticalScrollBar().value()
1645 self.__bPosFirst = value * self.BYTES_PER_LINE 1653 self.__bPosFirst = value * self.BYTES_PER_LINE
1646 self.__bPosLast = ( 1654 self.__bPosLast = self.__bPosFirst + self.__rowsShown * self.BYTES_PER_LINE - 1
1647 self.__bPosFirst + self.__rowsShown * self.BYTES_PER_LINE - 1
1648 )
1649 if self.__bPosLast >= self.__chunks.size(): 1655 if self.__bPosLast >= self.__chunks.size():
1650 self.__bPosLast = self.__chunks.size() - 1 1656 self.__bPosLast = self.__chunks.size() - 1
1651 self.__readBuffers() 1657 self.__readBuffers()
1652 self.setCursorPosition(self.__cursorPosition) 1658 self.setCursorPosition(self.__cursorPosition)
1653 1659
1654 @pyqtSlot(int) 1660 @pyqtSlot(int)
1655 def __dataChangedPrivate(self, idx=0): 1661 def __dataChangedPrivate(self, idx=0):
1656 """ 1662 """
1657 Private slot to handle data changes. 1663 Private slot to handle data changes.
1658 1664
1659 @param idx index 1665 @param idx index
1660 @type int 1666 @type int
1661 """ 1667 """
1662 self.__modified = ( 1668 self.__modified = (
1663 self.__undoStack.cleanIndex() == -1 or 1669 self.__undoStack.cleanIndex() == -1
1664 self.__undoStack.index() != self.__undoStack.cleanIndex()) 1670 or self.__undoStack.index() != self.__undoStack.cleanIndex()
1671 )
1665 self.__adjust() 1672 self.__adjust()
1666 self.dataChanged.emit(self.__modified) 1673 self.dataChanged.emit(self.__modified)
1667 1674
1668 @pyqtSlot() 1675 @pyqtSlot()
1669 def __refresh(self): 1676 def __refresh(self):
1670 """ 1677 """
1671 Private slot to refresh the display. 1678 Private slot to refresh the display.
1672 """ 1679 """
1673 self.ensureVisible() 1680 self.ensureVisible()
1674 self.__readBuffers() 1681 self.__readBuffers()
1675 1682
1676 @pyqtSlot() 1683 @pyqtSlot()
1677 def __updateCursor(self): 1684 def __updateCursor(self):
1678 """ 1685 """
1679 Private slot to update the blinking cursor. 1686 Private slot to update the blinking cursor.
1680 """ 1687 """

eric ide

mercurial