Mercurial > lcfOS
comparison python/ide/hexedit.py @ 333:dcae6574c974
Increment to qt5
author | Windel Bouwman |
---|---|
date | Sun, 09 Feb 2014 15:27:57 +0100 |
parents | 7b38782ed496 |
children | 11c5a8a70c02 |
comparison
equal
deleted
inserted
replaced
332:87feb8a23b4d | 333:dcae6574c974 |
---|---|
1 #!/usr/bin/python | 1 #!/usr/bin/python |
2 | 2 |
3 import sys | 3 import sys |
4 import os | 4 import os |
5 from PyQt4.QtCore import * | 5 from qtwrapper import QtGui, QtCore, QtWidgets, Qt |
6 from PyQt4.QtGui import * | 6 |
7 from PyQt4 import uic | |
8 | 7 |
9 BYTES_PER_LINE, GAP = 8, 12 | 8 BYTES_PER_LINE, GAP = 8, 12 |
10 | 9 |
11 def clamp(minimum, x, maximum): | 10 def clamp(minimum, x, maximum): |
12 return max(minimum, min(x, maximum)) | 11 return max(minimum, min(x, maximum)) |
15 if v < 0x20 or v > 0x7e: | 14 if v < 0x20 or v > 0x7e: |
16 return '.' | 15 return '.' |
17 else: | 16 else: |
18 return chr(v) | 17 return chr(v) |
19 | 18 |
20 class BinViewer(QWidget): | 19 class BinViewer(QtWidgets.QWidget): |
21 """ The view has an address, hex byte and ascii column """ | 20 """ The view has an address, hex byte and ascii column """ |
22 def __init__(self, scrollArea): | 21 def __init__(self, scrollArea): |
23 super().__init__(scrollArea) | 22 super().__init__(scrollArea) |
24 self.scrollArea = scrollArea | 23 self.scrollArea = scrollArea |
25 self.setFont(QFont('Courier', 16)) | 24 self.setFont(QtGui.QFont('Courier', 16)) |
26 self.setFocusPolicy(Qt.StrongFocus) | 25 self.setFocusPolicy(Qt.StrongFocus) |
27 self.blinkcursor = False | 26 self.blinkcursor = False |
28 self.cursorX = self.cursorY = 0 | 27 self.cursorX = self.cursorY = 0 |
29 self.scrollArea = scrollArea | 28 self.scrollArea = scrollArea |
30 self.Data = bytearray() | 29 self.Data = bytearray() |
31 self.Offset = 0 | 30 self.Offset = 0 |
32 t = QTimer(self) | 31 t = QtCore.QTimer(self) |
33 t.timeout.connect(self.updateCursor) | 32 t.timeout.connect(self.updateCursor) |
34 t.setInterval(500) | 33 t.setInterval(500) |
35 t.start() | 34 t.start() |
35 | |
36 def updateCursor(self): | 36 def updateCursor(self): |
37 self.blinkcursor = not self.blinkcursor | 37 self.blinkcursor = not self.blinkcursor |
38 self.update(self.cursorX, self.cursorY, self.charWidth, self.charHeight) | 38 self.update(self.cursorX, self.cursorY, self.charWidth, self.charHeight) |
39 | |
39 def setCursorPosition(self, position): | 40 def setCursorPosition(self, position): |
40 position = clamp(0, int(position), len(self.Data) * 2 - 1) | 41 position = clamp(0, int(position), len(self.Data) * 2 - 1) |
41 self.cursorPosition = position | 42 self.cursorPosition = position |
42 x = position % (2 * BYTES_PER_LINE) | 43 x = position % (2 * BYTES_PER_LINE) |
43 x = x + int(x / 2) # Create a gap between hex values | 44 x = x + int(x / 2) # Create a gap between hex values |
44 self.cursorX = self.xposHex + x * self.charWidth | 45 self.cursorX = self.xposHex + x * self.charWidth |
45 y = int(position / (2 * BYTES_PER_LINE)) | 46 y = int(position / (2 * BYTES_PER_LINE)) |
46 self.cursorY = y * self.charHeight + 2 | 47 self.cursorY = y * self.charHeight + 2 |
47 self.blinkcursor = True | 48 self.blinkcursor = True |
48 self.update() | 49 self.update() |
50 | |
49 def getCursorPosition(self): | 51 def getCursorPosition(self): |
50 return self.cursorPosition | 52 return self.cursorPosition |
51 CursorPosition = property(getCursorPosition, setCursorPosition) | 53 CursorPosition = property(getCursorPosition, setCursorPosition) |
52 def setOffset(self, off): | 54 def setOffset(self, off): |
53 self.offset = off | 55 self.offset = off |
54 self.update() | 56 self.update() |
57 | |
55 Offset = property(lambda self: self.offset, setOffset) | 58 Offset = property(lambda self: self.offset, setOffset) |
56 def paintEvent(self, event): | 59 def paintEvent(self, event): |
57 # Helper variables: | 60 # Helper variables: |
58 er = event.rect() | 61 er = event.rect() |
59 chw, chh = self.charWidth, self.charHeight | 62 chw, chh = self.charWidth, self.charHeight |
60 painter = QPainter(self) | 63 painter = QtGui.QPainter(self) |
61 # Background: | 64 # Background: |
62 painter.fillRect(er, self.palette().color(QPalette.Base)) | 65 painter.fillRect(er, self.palette().color(QtGui.QPalette.Base)) |
63 painter.fillRect(QRect(self.xposAddr, er.top(), 8 * chw, er.bottom() + 1), Qt.gray) | 66 painter.fillRect(QtCore.QRect(self.xposAddr, er.top(), 8 * chw, er.bottom() + 1), Qt.gray) |
64 painter.setPen(Qt.gray) | 67 painter.setPen(Qt.gray) |
65 x = self.xposAscii - (GAP / 2) | 68 x = self.xposAscii - (GAP / 2) |
66 painter.drawLine(x, er.top(), x, er.bottom()) | 69 painter.drawLine(x, er.top(), x, er.bottom()) |
67 x = self.xposEnd - (GAP / 2) | 70 x = self.xposEnd - (GAP / 2) |
68 painter.drawLine(x, er.top(), x, er.bottom()) | 71 painter.drawLine(x, er.top(), x, er.bottom()) |
92 xposAscii += chw | 95 xposAscii += chw |
93 ypos += chh | 96 ypos += chh |
94 # cursor | 97 # cursor |
95 if self.blinkcursor: | 98 if self.blinkcursor: |
96 painter.fillRect(self.cursorX, self.cursorY + chh - 2, chw, 2, Qt.black) | 99 painter.fillRect(self.cursorX, self.cursorY + chh - 2, chw, 2, Qt.black) |
100 | |
97 def keyPressEvent(self, event): | 101 def keyPressEvent(self, event): |
98 if event.matches(QKeySequence.MoveToNextChar): | 102 if event.matches(QKeySequence.MoveToNextChar): |
99 self.CursorPosition += 1 | 103 self.CursorPosition += 1 |
100 if event.matches(QKeySequence.MoveToPreviousChar): | 104 if event.matches(QKeySequence.MoveToPreviousChar): |
101 self.CursorPosition -= 1 | 105 self.CursorPosition -= 1 |
120 else: | 124 else: |
121 self.data[i] = (self.data[i] & 0xF0) | v | 125 self.data[i] = (self.data[i] & 0xF0) | v |
122 self.CursorPosition += 1 | 126 self.CursorPosition += 1 |
123 self.scrollArea.ensureVisible(self.cursorX, self.cursorY + self.charHeight / 2, 4, self.charHeight / 2 + 4) | 127 self.scrollArea.ensureVisible(self.cursorX, self.cursorY + self.charHeight / 2, 4, self.charHeight / 2 + 4) |
124 self.update() | 128 self.update() |
129 | |
125 def setCursorPositionAt(self, pos): | 130 def setCursorPositionAt(self, pos): |
126 """ Calculate cursor position at a certain point """ | 131 """ Calculate cursor position at a certain point """ |
127 if pos.x() > self.xposHex and pos.x() < self.xposAscii: | 132 if pos.x() > self.xposHex and pos.x() < self.xposAscii: |
128 x = round((2 * (pos.x() - self.xposHex)) / (self.charWidth * 3)) | 133 x = round((2 * (pos.x() - self.xposHex)) / (self.charWidth * 3)) |
129 y = int(pos.y() / self.charHeight) * 2 * BYTES_PER_LINE | 134 y = int(pos.y() / self.charHeight) * 2 * BYTES_PER_LINE |
130 self.setCursorPosition(x + y) | 135 self.setCursorPosition(x + y) |
136 | |
131 def mousePressEvent(self, event): | 137 def mousePressEvent(self, event): |
132 self.setCursorPositionAt(event.pos()) | 138 self.setCursorPositionAt(event.pos()) |
139 | |
133 def adjust(self): | 140 def adjust(self): |
134 self.charHeight = self.fontMetrics().height() | 141 self.charHeight = self.fontMetrics().height() |
135 self.charWidth = self.fontMetrics().width('x') | 142 self.charWidth = self.fontMetrics().width('x') |
136 self.xposAddr = GAP | 143 self.xposAddr = GAP |
137 self.xposHex = self.xposAddr + 8 * self.charWidth + GAP | 144 self.xposHex = self.xposAddr + 8 * self.charWidth + GAP |
144 r = len(self.Data) % BYTES_PER_LINE | 151 r = len(self.Data) % BYTES_PER_LINE |
145 r = 1 if r > 0 else 0 | 152 r = 1 if r > 0 else 0 |
146 self.setMinimumHeight((int(len(self.Data) / BYTES_PER_LINE) + r) * self.charHeight + 4) | 153 self.setMinimumHeight((int(len(self.Data) / BYTES_PER_LINE) + r) * self.charHeight + 4) |
147 self.scrollArea.setMinimumHeight(self.charHeight * 8) | 154 self.scrollArea.setMinimumHeight(self.charHeight * 8) |
148 self.update() | 155 self.update() |
156 | |
149 def showEvent(self, e): | 157 def showEvent(self, e): |
150 self.adjust() | 158 self.adjust() |
151 super().showEvent(e) | 159 super().showEvent(e) |
160 | |
152 def setData(self, d): | 161 def setData(self, d): |
153 self.data = bytearray(d) | 162 self.data = bytearray(d) |
154 self.originalData = bytearray(d) | 163 self.originalData = bytearray(d) |
155 self.adjust() | 164 self.adjust() |
156 self.setCursorPosition(0) | 165 self.setCursorPosition(0) |
157 Data = property(lambda self: self.data, setData) | 166 Data = property(lambda self: self.data, setData) |
158 | 167 |
159 class HexEdit(QScrollArea): | 168 |
169 class HexEdit(QtWidgets.QScrollArea): | |
160 def __init__(self): | 170 def __init__(self): |
161 super().__init__() | 171 super().__init__() |
162 self.bv = BinViewer(self) | 172 self.bv = BinViewer(self) |
163 self.setWidget(self.bv) | 173 self.setWidget(self.bv) |
164 self.setWidgetResizable(True) | 174 self.setWidgetResizable(True) |
165 self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn) | 175 self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn) |
166 self.setFocusPolicy(Qt.NoFocus) | 176 self.setFocusPolicy(Qt.NoFocus) |
167 | 177 |
168 class HexEditor(QMainWindow): | 178 |
179 class HexEditor(QtWidgets.QMainWindow): | |
169 def __init__(self): | 180 def __init__(self): |
170 super().__init__() | 181 super().__init__() |
171 basedir = os.path.dirname(__file__) | 182 basedir = os.path.dirname(__file__) |
172 uic.loadUi(os.path.join(basedir, 'hexeditor.ui'), baseinstance=self) | 183 uic.loadUi(os.path.join(basedir, 'hexeditor.ui'), baseinstance=self) |
173 self.he = HexEdit() | 184 self.he = HexEdit() |
196 with open(filename, 'wb') as f: | 207 with open(filename, 'wb') as f: |
197 f.write(self.he.bv.Data) | 208 f.write(self.he.bv.Data) |
198 self.fileName = filename | 209 self.fileName = filename |
199 self.updateControls() | 210 self.updateControls() |
200 | 211 |
212 | |
201 if __name__ == '__main__': | 213 if __name__ == '__main__': |
202 app = QApplication(sys.argv) | 214 app = QApplication(sys.argv) |
203 he = HexEditor() | 215 he = HexEditor() |
204 he.show() | 216 he.show() |
205 #he.bv.Data = bytearray(range(100)) * 8 + b'x' | 217 #he.bv.Data = bytearray(range(100)) * 8 + b'x' |
206 app.exec() | 218 app.exec() |
207 |