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) |
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): |
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: |
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 """ |