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