annotate python/hexedit.py @ 135:01d88140dc03

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