Mercurial > lcfOS
comparison python/hexedit.py @ 135:01d88140dc03
Improve hexedit
author | Windel Bouwman |
---|---|
date | Mon, 21 Jan 2013 21:12:36 +0100 |
parents | 1a50d6db24ed |
children | 9af544be5d2a |
comparison
equal
deleted
inserted
replaced
134:1a50d6db24ed | 135:01d88140dc03 |
---|---|
6 GAP = 16 | 6 GAP = 16 |
7 | 7 |
8 class BinViewer(QWidget): | 8 class BinViewer(QWidget): |
9 """ The view has an address, hex byte and ascii column """ | 9 """ The view has an address, hex byte and ascii column """ |
10 def __init__(self, scrollArea): | 10 def __init__(self, scrollArea): |
11 super().__init__() | 11 super().__init__(scrollArea) |
12 self.setFont(QFont('Courier', 10)) | 12 self.scrollArea = scrollArea |
13 self.setFont(QFont('Courier', 18)) | |
13 self.setFocusPolicy(Qt.StrongFocus) | 14 self.setFocusPolicy(Qt.StrongFocus) |
14 self.blinkcursor = False | 15 self.blinkcursor = False |
15 self.cursorX = 0 | 16 self.cursorX = 0 |
16 self.cursorY = 0 | 17 self.cursorY = 0 |
17 self.scrollArea = scrollArea | 18 self.scrollArea = scrollArea |
22 t.start() | 23 t.start() |
23 def updateCursor(self): | 24 def updateCursor(self): |
24 self.blinkcursor = not self.blinkcursor | 25 self.blinkcursor = not self.blinkcursor |
25 self.update(self.cursorX, self.cursorY, self.charWidth, self.charHeight) | 26 self.update(self.cursorX, self.cursorY, self.charWidth, self.charHeight) |
26 def setCursorPosition(self, position): | 27 def setCursorPosition(self, position): |
28 position = int(position) | |
27 if position > len(self.Data) * 2 - 1: | 29 if position > len(self.Data) * 2 - 1: |
28 position = len(self.Data) * 2 - 1 | 30 position = len(self.Data) * 2 - 1 |
29 if position < 0: | 31 if position < 0: |
30 position = 0 | 32 position = 0 |
31 self.cursorPosition = position | 33 self.cursorPosition = position |
32 x = position % (2 * BYTES_PER_LINE) | 34 x = position % (2 * BYTES_PER_LINE) |
33 self.cursorX = self.xposHex + x * self.charWidth | 35 self.cursorX = self.xposHex + x * self.charWidth |
34 self.cursorY = int(position / (2 * BYTES_PER_LINE)) * self.charHeight + 4 | 36 self.cursorY = int(position / (2 * BYTES_PER_LINE)) * self.charHeight + 4 |
35 self.blinkcursor = True | 37 self.blinkcursor = True |
36 self.update() | 38 self.update() |
39 def getCursorPosition(self): | |
40 return self.cursorPosition | |
41 CursorPosition = property(getCursorPosition, setCursorPosition) | |
37 def paintEvent(self, event): | 42 def paintEvent(self, event): |
38 painter = QPainter(self) | 43 painter = QPainter(self) |
39 # Background: | 44 # Background: |
40 painter.fillRect(event.rect(), self.palette().color(QPalette.Base)) | 45 painter.fillRect(event.rect(), self.palette().color(QPalette.Base)) |
41 painter.fillRect(QRect(self.xposAddr, event.rect().top(), self.xposHex, self.height()), Qt.yellow) | 46 painter.fillRect(QRect(self.xposAddr, event.rect().top(), self.xposHex, self.height()), Qt.gray) |
47 painter.setPen(Qt.gray) | |
48 x = self.xposAscii - (GAP / 2) | |
49 painter.drawLine(x, event.rect().top(), x, self.height()) | |
42 | 50 |
43 painter.setPen(Qt.black) | 51 painter.setPen(Qt.black) |
44 # first and last index | 52 # first and last index |
45 firstIndex = (int(event.rect().top() / self.charHeight) - self.charHeight) * BYTES_PER_LINE | 53 firstIndex = (int(event.rect().top() / self.charHeight) - self.charHeight) * BYTES_PER_LINE |
46 if firstIndex < 0: | 54 if firstIndex < 0: |
53 ypos = yposStart | 61 ypos = yposStart |
54 for index in range(firstIndex, lastIndex, BYTES_PER_LINE): | 62 for index in range(firstIndex, lastIndex, BYTES_PER_LINE): |
55 painter.drawText(self.xposAddr, ypos, '{0:08X}'.format(index)) | 63 painter.drawText(self.xposAddr, ypos, '{0:08X}'.format(index)) |
56 | 64 |
57 xpos = self.xposHex | 65 xpos = self.xposHex |
66 xposA = self.xposAscii | |
58 for colIndex in range(BYTES_PER_LINE): | 67 for colIndex in range(BYTES_PER_LINE): |
59 if index + colIndex < len(self.Data): | 68 if index + colIndex < len(self.Data): |
60 b = '{0:02X}'.format(self.Data[index + colIndex]) | 69 b = self.Data[index + colIndex] |
61 painter.drawText(xpos, ypos, b) | 70 bhex = '{0:02X}'.format(b) |
71 ba = chr(b) | |
72 painter.drawText(xpos, ypos, bhex) | |
73 painter.drawText(xposA, ypos, ba) | |
62 xpos += 2 * self.charWidth | 74 xpos += 2 * self.charWidth |
75 xposA += self.charWidth | |
63 ypos += self.charHeight | 76 ypos += self.charHeight |
64 | 77 |
65 # cursor | 78 # cursor |
66 if self.blinkcursor: | 79 if self.blinkcursor: |
67 painter.fillRect(self.cursorX, self.cursorY + self.charHeight - 2, self.charWidth, 2, Qt.blue) | 80 painter.fillRect(self.cursorX, self.cursorY + self.charHeight - 2, self.charWidth, 2, Qt.black) |
68 def keyPressEvent(self, event): | 81 def keyPressEvent(self, event): |
69 if event.matches(QKeySequence.MoveToNextChar): | 82 if event.matches(QKeySequence.MoveToNextChar): |
70 self.setCursorPosition(self.cursorPosition + 1) | 83 self.CursorPosition += 1 |
71 if event.matches(QKeySequence.MoveToPreviousChar): | 84 if event.matches(QKeySequence.MoveToPreviousChar): |
72 self.setCursorPosition(self.cursorPosition - 1) | 85 self.CursorPosition -= 1 |
73 if event.matches(QKeySequence.MoveToNextLine): | 86 if event.matches(QKeySequence.MoveToNextLine): |
74 self.setCursorPosition(self.cursorPosition + 2 * BYTES_PER_LINE) | 87 self.CursorPosition += 2 * BYTES_PER_LINE |
75 if event.matches(QKeySequence.MoveToPreviousLine): | 88 if event.matches(QKeySequence.MoveToPreviousLine): |
76 self.setCursorPosition(self.cursorPosition - 2 * BYTES_PER_LINE) | 89 self.CursorPosition -= 2 * BYTES_PER_LINE |
77 self.ensureVisible() | 90 char = event.text().lower() |
91 if char and char in '0123456789abcdef': | |
92 i = int(self.CursorPosition / 2) | |
93 hb = self.CursorPosition % 2 | |
94 v = int(char, 16) | |
95 if hb == 0: | |
96 # high half byte | |
97 self.data[i] = (self.data[i] & 0xF) | (v << 4) | |
98 else: | |
99 self.data[i] = (self.data[i] & 0xF0) | v | |
100 self.CursorPosition += 1 | |
101 self.scrollArea.ensureVisible(self.cursorX, self.cursorY, self.charWidth, self.charHeight + 2) | |
78 self.update() | 102 self.update() |
79 def ensureVisible(self): | 103 def cursorPositionAt(self, pos): |
80 self.scrollArea.ensureVisible(self.cursorX, self.cursorY + self.charHeight, 3, self.charHeight / 2 + 2) | 104 """ Calculate cursor position at a certain point """ |
105 if pos.x() > self.xposHex and pos.x() < self.xposAscii: | |
106 x = (pos.x() - self.xposHex) / self.charWidth | |
107 y = int(pos.y() / self.charHeight) * 2 * BYTES_PER_LINE | |
108 return x + y | |
109 return 0 | |
110 def mousePressEvent(self, event): | |
111 cpos = self.cursorPositionAt(event.pos()) | |
112 self.setCursorPosition(cpos) | |
81 def adjust(self): | 113 def adjust(self): |
82 self.charHeight = self.fontMetrics().height() | 114 self.charHeight = self.fontMetrics().height() |
83 self.charWidth = self.fontMetrics().width('x') | 115 self.charWidth = self.fontMetrics().width('x') |
84 self.xposAddr = 2 | 116 self.xposAddr = 2 |
85 self.xposHex = self.xposAddr + 8 * self.charWidth + GAP | 117 self.xposHex = self.xposAddr + 8 * self.charWidth + GAP |
86 self.xposAscii = self.xposHex + (BYTES_PER_LINE * 3 - 1) * self.charWidth + GAP | 118 self.xposAscii = self.xposHex + (BYTES_PER_LINE * 2) * self.charWidth + GAP |
87 self.setMinimumWidth(self.xposAscii + self.charWidth * BYTES_PER_LINE) | 119 self.setMinimumWidth(self.xposAscii + self.charWidth * BYTES_PER_LINE) |
120 self.scrollArea.setMinimumWidth(self.xposAscii + self.charWidth * BYTES_PER_LINE) | |
88 self.setMinimumHeight((int(len(self.Data) / BYTES_PER_LINE) + 1) * self.charHeight) | 121 self.setMinimumHeight((int(len(self.Data) / BYTES_PER_LINE) + 1) * self.charHeight) |
89 self.update() | |
90 def getBytes(self, offset): | |
91 return bytes() | |
92 def setHexFile(self, hf): | |
93 self.hexfile = hf | |
94 self.update() | 122 self.update() |
95 def getData(self): | 123 def getData(self): |
96 return self.data | 124 return self.data |
97 def setData(self, d): | 125 def setData(self, d): |
98 self.data = d | 126 self.data = d |
101 Data = property(getData, setData) | 129 Data = property(getData, setData) |
102 | 130 |
103 class HexEdit(QScrollArea): | 131 class HexEdit(QScrollArea): |
104 def __init__(self): | 132 def __init__(self): |
105 super().__init__() | 133 super().__init__() |
106 self.setWidgetResizable(True) | |
107 self.bv = BinViewer(self) | 134 self.bv = BinViewer(self) |
108 self.setWidget(self.bv) | 135 self.setWidget(self.bv) |
136 self.setWidgetResizable(True) | |
109 self.setFocusPolicy(Qt.NoFocus) | 137 self.setFocusPolicy(Qt.NoFocus) |
110 | 138 |
111 if __name__ == '__main__': | 139 if __name__ == '__main__': |
112 app = QApplication(sys.argv) | 140 app = QApplication(sys.argv) |
113 he = HexEdit() | 141 he = HexEdit() |
114 he.show() | 142 he.show() |
115 he.bv.Data = bytearray(range(100)) * 8 | 143 he.bv.Data = bytearray(range(100)) * 8 + b'hjkfd' |
116 app.exec() | 144 app.exec() |
117 | 145 |