Mercurial > lcfOS
comparison python/hexedit.py @ 133:a816c683c1c0
Fixes in hexedit
author | Windel Bouwman |
---|---|
date | Sun, 20 Jan 2013 21:48:41 +0100 |
parents | 205578c96a79 |
children | 1a50d6db24ed |
comparison
equal
deleted
inserted
replaced
132:205578c96a79 | 133:a816c683c1c0 |
---|---|
1 | 1 import sys |
2 from PyQt4.QtCore import * | 2 from PyQt4.QtCore import * |
3 from PyQt4.QtGui import * | 3 from PyQt4.QtGui import * |
4 | |
5 BYTES_PER_LINE = 8 | |
6 GAP = 16 | |
7 | |
8 class BinViewer(QWidget): | |
9 """ The view has an address, hex byte and ascii column """ | |
10 def __init__(self): | |
11 super().__init__() | |
12 self.setFont(QFont('Courier', 10)) | |
13 self.setFocusPolicy(Qt.StrongFocus) | |
14 self.blinkcursor = False | |
15 self.Data = bytearray() | |
16 t = QTimer(self) | |
17 t.timeout.connect(self.updateCursor) | |
18 t.setInterval(500) | |
19 t.start() | |
20 self.cursorX = 0 | |
21 self.cursorY = 0 | |
22 def updateCursor(self): | |
23 self.blinkcursor = not self.blinkcursor | |
24 self.update(self.cursorX, self.cursorY, self.charWidth, self.charHeight) | |
25 def setCursorPosition(self, position): | |
26 if position > len(self.Data) * 2 - 1: | |
27 position = len(self.Data) * 2 - 1 | |
28 if position < 0: | |
29 position = 0 | |
30 self.cursorPosition = position | |
31 x = position % (2 * BYTES_PER_LINE) | |
32 self.cursorX = self.xposHex + x * self.charWidth | |
33 self.cursorY = int(position / (2 * BYTES_PER_LINE)) * self.charHeight + 4 | |
34 self.blinkcursor = True | |
35 self.update() | |
36 def paintEvent(self, event): | |
37 painter = QPainter(self) | |
38 # Background: | |
39 painter.fillRect(event.rect(), self.palette().color(QPalette.Base)) | |
40 painter.fillRect(QRect(self.xposAddr, event.rect().top(), self.xposHex, self.height()), Qt.yellow) | |
41 | |
42 painter.setPen(Qt.black) | |
43 # first and last index | |
44 firstIndex = (int(event.rect().top() / self.charHeight) - self.charHeight) * BYTES_PER_LINE | |
45 if firstIndex < 0: | |
46 firstIndex = 0 | |
47 lastIndex = (int(event.rect().bottom() / self.charHeight) + self.charHeight) * BYTES_PER_LINE | |
48 if lastIndex < 0: | |
49 lastIndex = 0 | |
50 yposStart = int(firstIndex / BYTES_PER_LINE) * self.charHeight + self.charHeight | |
51 | |
52 ypos = yposStart | |
53 for index in range(firstIndex, lastIndex, BYTES_PER_LINE): | |
54 xpos = self.xposHex | |
55 for colIndex in range(BYTES_PER_LINE): | |
56 if index + colIndex < len(self.Data): | |
57 b = '{0:02X}'.format(self.Data[index + colIndex]) | |
58 painter.drawText(xpos, ypos, b) | |
59 xpos += 2 * self.charWidth | |
60 ypos += self.charHeight | |
61 | |
62 # cursor | |
63 if self.blinkcursor: | |
64 painter.fillRect(self.cursorX, self.cursorY + self.charHeight - 2, self.charWidth, 2, Qt.blue) | |
65 def keyPressEvent(self, event): | |
66 if event.matches(QKeySequence.MoveToNextChar): | |
67 self.setCursorPosition(self.cursorPosition + 1) | |
68 if event.matches(QKeySequence.MoveToPreviousChar): | |
69 self.setCursorPosition(self.cursorPosition - 1) | |
70 if event.matches(QKeySequence.MoveToNextLine): | |
71 self.setCursorPosition(self.cursorPosition + 2 * BYTES_PER_LINE) | |
72 if event.matches(QKeySequence.MoveToPreviousLine): | |
73 self.setCursorPosition(self.cursorPosition - 2 * BYTES_PER_LINE) | |
74 | |
75 def adjust(self): | |
76 self.charHeight = self.fontMetrics().height() | |
77 self.charWidth = self.fontMetrics().width('x') | |
78 self.xposAddr = 2 | |
79 self.xposHex = self.xposAddr + 8 * self.charWidth + GAP | |
80 self.xposAscii = self.xposHex + (BYTES_PER_LINE * 3 - 1) * self.charWidth + GAP | |
81 self.setMinimumWidth(self.xposAscii + self.charWidth * BYTES_PER_LINE) | |
82 self.setMinimumHeight((int(len(self.Data) / BYTES_PER_LINE) + 1) * self.charHeight) | |
83 self.update() | |
84 def getBytes(self, offset): | |
85 return bytes() | |
86 def setHexFile(self, hf): | |
87 self.hexfile = hf | |
88 self.update() | |
89 def getData(self): | |
90 return self.data | |
91 def setData(self, d): | |
92 self.data = d | |
93 self.adjust() | |
94 self.setCursorPosition(0) | |
95 Data = property(getData, setData) | |
4 | 96 |
5 class HexEdit(QScrollArea): | 97 class HexEdit(QScrollArea): |
6 def __init__(self): | 98 def __init__(self): |
7 super().__init__() | 99 super().__init__() |
100 self.setWidgetResizable(True) | |
101 self.bv = BinViewer() | |
102 self.setWidget(self.bv) | |
103 self.setFocusPolicy(Qt.NoFocus) | |
8 | 104 |
9 class BinViewer(QWidget): | 105 if __name__ == '__main__': |
10 """ | 106 app = QApplication(sys.argv) |
11 The binviewer consists of a hex view, a ascii view | 107 he = HexEdit() |
12 and perhaps others.. | 108 he.show() |
13 """ | 109 he.bv.Data = bytearray(range(100)) * 8 |
14 def __init__(self): | 110 app.exec() |
15 super().__init__() | 111 |
16 self.setFont(QFont('Courier')) | |
17 self.fontHeight = self.fontMetrics().height() | |
18 self.fontWidth = self.fontMetrics().width('x') | |
19 self.hexfile = hexfile.HexFile() | |
20 def paintEvent(self, event): | |
21 painter = QPainter(self) | |
22 br = QBrush(Qt.lightGray) | |
23 painter.setBrush(br) | |
24 h = self.height() | |
25 addressWidth = self.fontWidth * 8 | |
26 painter.drawRect(2, 2, addressWidth, h) | |
27 br2 = QBrush(Qt.yellow) | |
28 painter.setBrush(br2) | |
29 w = self.width() | |
30 byteWidth = self.fontWidth * (16 * 3 - 1) | |
31 painter.drawRect(addressWidth + 4, 2, byteWidth, h) | |
32 asciiWidth = self.fontWidth * 16 | |
33 br2 = QBrush(Qt.gray) | |
34 painter.setBrush(br2) | |
35 painter.drawRect(addressWidth + byteWidth + 4, 2, asciiWidth, h) | |
36 rows = int(h / self.fontHeight) + 1 | |
37 offset = 0 | |
38 for r in range(1, rows): | |
39 bts = self.getBytes(offset + r - 1) | |
40 addr = '{0:08X}'.format(r << 16) | |
41 painter.drawText(2, 2 + self.fontHeight * r, addr) | |
42 x = addressWidth + 4 | |
43 for b in bts: | |
44 b = '{0:02X}'.format(b) | |
45 painter.drawText(x, 2 + self.fontHeight * r, b) | |
46 x += 3 * self.fontWidth | |
47 x = addressWidth + byteWidth + 4 | |
48 for b in bts: | |
49 b = '{0}'.format(chr(b)) | |
50 painter.drawText(x, 2 + self.fontHeight * r, b) | |
51 x += 1 * self.fontWidth | |
52 def getBytes(self, offset): | |
53 if self.hexfile.regions: | |
54 r = self.hexfile.regions[0] | |
55 chunks = [r.data[p:p+16] for p in range(0, len(r.data), 16)] | |
56 if len(chunks) > offset: | |
57 return chunks[offset] | |
58 return bytes() | |
59 def setHexFile(self, hf): | |
60 self.hexfile = hf | |
61 self.update() |