Mercurial > lcfOS
changeset 136:9af544be5d2a
Added hexfile edit
author | Windel Bouwman |
---|---|
date | Wed, 23 Jan 2013 21:54:14 +0100 |
parents | 01d88140dc03 |
children | 0a540ce31cd5 |
files | python/hexedit.py python/ide.py python/st-util.py |
diffstat | 3 files changed, 88 insertions(+), 40 deletions(-) [+] |
line wrap: on
line diff
--- a/python/hexedit.py Mon Jan 21 21:12:36 2013 +0100 +++ b/python/hexedit.py Wed Jan 23 21:54:14 2013 +0100 @@ -3,7 +3,16 @@ from PyQt4.QtGui import * BYTES_PER_LINE = 8 -GAP = 16 +GAP = 12 + +def clamp(minimum, x, maximum): + return max(minimum, min(x, maximum)) + +def asciiChar(v): + if v < 0x20 or v > 0x7e: + return '.' + else: + return chr(v) class BinViewer(QWidget): """ The view has an address, hex byte and ascii column """ @@ -13,10 +22,10 @@ self.setFont(QFont('Courier', 18)) self.setFocusPolicy(Qt.StrongFocus) self.blinkcursor = False - self.cursorX = 0 - self.cursorY = 0 + self.cursorX = self.cursorY = 0 self.scrollArea = scrollArea self.Data = bytearray() + self.Offset = 0 t = QTimer(self) t.timeout.connect(self.updateCursor) t.setInterval(500) @@ -25,59 +34,57 @@ self.blinkcursor = not self.blinkcursor self.update(self.cursorX, self.cursorY, self.charWidth, self.charHeight) def setCursorPosition(self, position): - position = int(position) - if position > len(self.Data) * 2 - 1: - position = len(self.Data) * 2 - 1 - if position < 0: - position = 0 + position = clamp(0, int(position), len(self.Data) * 2 - 1) self.cursorPosition = position x = position % (2 * BYTES_PER_LINE) self.cursorX = self.xposHex + x * self.charWidth - self.cursorY = int(position / (2 * BYTES_PER_LINE)) * self.charHeight + 4 + self.cursorY = int(position / (2 * BYTES_PER_LINE)) * self.charHeight + 2 self.blinkcursor = True self.update() def getCursorPosition(self): return self.cursorPosition CursorPosition = property(getCursorPosition, setCursorPosition) + def getOffset(self): + return self.offset + def setOffset(self, off): + self.offset = off + self.update() + Offset = property(getOffset, setOffset) def paintEvent(self, event): + # Helper variables: + er = event.rect() + chw, chh = self.charWidth, self.charHeight painter = QPainter(self) # Background: - painter.fillRect(event.rect(), self.palette().color(QPalette.Base)) - painter.fillRect(QRect(self.xposAddr, event.rect().top(), self.xposHex, self.height()), Qt.gray) + painter.fillRect(er, self.palette().color(QPalette.Base)) + painter.fillRect(QRect(self.xposAddr, er.top(), 8 * chw, er.bottom() + 1), Qt.gray) painter.setPen(Qt.gray) x = self.xposAscii - (GAP / 2) - painter.drawLine(x, event.rect().top(), x, self.height()) - - painter.setPen(Qt.black) + painter.drawLine(x, er.top(), x, er.bottom()) + x = self.xposEnd - (GAP / 2) + painter.drawLine(x, er.top(), x, er.bottom()) # first and last index - firstIndex = (int(event.rect().top() / self.charHeight) - self.charHeight) * BYTES_PER_LINE - if firstIndex < 0: - firstIndex = 0 - lastIndex = (int(event.rect().bottom() / self.charHeight) + self.charHeight) * BYTES_PER_LINE - if lastIndex < 0: - lastIndex = 0 - yposStart = int(firstIndex / BYTES_PER_LINE) * self.charHeight + self.charHeight - + firstIndex = max((int(er.top() / chh) - chh) * BYTES_PER_LINE, 0) + lastIndex = max((int(er.bottom() / chh) + chh) * BYTES_PER_LINE, 0) + yposStart = int(firstIndex / BYTES_PER_LINE) * chh + chh + # Draw contents: + painter.setPen(Qt.black) ypos = yposStart for index in range(firstIndex, lastIndex, BYTES_PER_LINE): - painter.drawText(self.xposAddr, ypos, '{0:08X}'.format(index)) - + painter.drawText(self.xposAddr, ypos, '{0:08X}'.format(index + self.Offset)) xpos = self.xposHex - xposA = self.xposAscii + xposAscii = self.xposAscii for colIndex in range(BYTES_PER_LINE): if index + colIndex < len(self.Data): b = self.Data[index + colIndex] - bhex = '{0:02X}'.format(b) - ba = chr(b) - painter.drawText(xpos, ypos, bhex) - painter.drawText(xposA, ypos, ba) - xpos += 2 * self.charWidth - xposA += self.charWidth - ypos += self.charHeight - + painter.drawText(xpos, ypos, '{0:02X}'.format(b)) + painter.drawText(xposAscii, ypos, asciiChar(b)) + xpos += 2 * chw + xposAscii += chw + ypos += chh # cursor if self.blinkcursor: - painter.fillRect(self.cursorX, self.cursorY + self.charHeight - 2, self.charWidth, 2, Qt.black) + painter.fillRect(self.cursorX, self.cursorY + chh - 2, chw, 2, Qt.black) def keyPressEvent(self, event): if event.matches(QKeySequence.MoveToNextChar): self.CursorPosition += 1 @@ -87,6 +94,12 @@ self.CursorPosition += 2 * BYTES_PER_LINE if event.matches(QKeySequence.MoveToPreviousLine): self.CursorPosition -= 2 * BYTES_PER_LINE + if event.matches(QKeySequence.MoveToNextPage): + rows = int(self.scrollArea.viewport().height() / self.charHeight) + self.CursorPosition += (rows - 1) * 2 * BYTES_PER_LINE + if event.matches(QKeySequence.MoveToPreviousPage): + rows = int(self.scrollArea.viewport().height() / self.charHeight) + self.CursorPosition -= (rows - 1) * 2 * BYTES_PER_LINE char = event.text().lower() if char and char in '0123456789abcdef': i = int(self.CursorPosition / 2) @@ -113,12 +126,15 @@ def adjust(self): self.charHeight = self.fontMetrics().height() self.charWidth = self.fontMetrics().width('x') - self.xposAddr = 2 + self.xposAddr = GAP self.xposHex = self.xposAddr + 8 * self.charWidth + GAP - self.xposAscii = self.xposHex + (BYTES_PER_LINE * 2) * self.charWidth + GAP - self.setMinimumWidth(self.xposAscii + self.charWidth * BYTES_PER_LINE) - self.scrollArea.setMinimumWidth(self.xposAscii + self.charWidth * BYTES_PER_LINE) + self.xposAscii = self.xposHex + BYTES_PER_LINE * 2 * self.charWidth + GAP + self.xposEnd = self.xposAscii + self.charWidth * BYTES_PER_LINE + GAP + self.setMinimumWidth(self.xposEnd) + sbw = self.scrollArea.verticalScrollBar().width() + self.scrollArea.setMinimumWidth(self.xposEnd + sbw + 5) self.setMinimumHeight((int(len(self.Data) / BYTES_PER_LINE) + 1) * self.charHeight) + self.scrollArea.setMinimumHeight(self.charHeight * 8) self.update() def getData(self): return self.data @@ -134,6 +150,7 @@ self.bv = BinViewer(self) self.setWidget(self.bv) self.setWidgetResizable(True) + self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn) self.setFocusPolicy(Qt.NoFocus) if __name__ == '__main__':
--- a/python/ide.py Mon Jan 21 21:12:36 2013 +0100 +++ b/python/ide.py Wed Jan 23 21:54:14 2013 +0100 @@ -150,7 +150,9 @@ self.projectview.sigLoadFile.connect(self.loadFile) self.devxplr = addComponent('Device explorer', stutil.DeviceExplorer()) self.regview = addComponent('Registers', stutil.RegisterView()) + self.memview = addComponent('Memory', stutil.MemoryView()) self.devxplr.deviceSelected.connect(self.regview.mdl.setDevice) + self.devxplr.deviceSelected.connect(self.memview.setDevice) # About dialog: self.aboutDialog = AboutDialog()
--- a/python/st-util.py Mon Jan 21 21:12:36 2013 +0100 +++ b/python/st-util.py Wed Jan 23 21:54:14 2013 +0100 @@ -5,6 +5,7 @@ from PyQt4.QtGui import * import stlink, devices, stm32 from devices import Interface, Device +from hexedit import HexEdit class InformationDialog(QDialog): def __init__(self, parent): @@ -52,8 +53,36 @@ self.mdl = RegisterModel() self.setModel(self.mdl) -class MemoryViewer(QWidget): - pass +class MemoryView(QWidget): + def __init__(self): + super().__init__() + l = QVBoxLayout(self) + l2 = QHBoxLayout() + l2.addWidget(QLabel('Address')) + self.addressLine = QLineEdit() + self.addressLine.setInputMask('Hhhhhhhh') + self.addressLine.setText('08000000') + l2.addWidget(self.addressLine) + l.addLayout(l2) + self.device = None + self.hexEdit = HexEdit() + self.loadAddress(0x8000000) + l.addWidget(self.hexEdit) + self.addressLine.returnPressed.connect(self.doLoad) + def doLoad(self): + txt = self.addressLine.text() + self.loadAddress(int(txt, 16)) + def loadAddress(self, address): + size = 512 + if self.device: + data = self.device.iface.read_mem32(address, size) + else: + data = bytearray(size) + self.hexEdit.bv.Data = data + self.hexEdit.bv.Offset = address + def setDevice(self, dev): + self.device = dev + self.loadAddress(0x8000000) class FlashTool(QWidget): def __init__(self):