Mercurial > lcfOS
diff python/codeedit.py @ 160:10330be89bc2
Started from scratch with code edit
author | Windel Bouwman |
---|---|
date | Sat, 09 Mar 2013 11:56:48 +0100 |
parents | |
children | 956f8e5ee48a |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/python/codeedit.py Sat Mar 09 11:56:48 2013 +0100 @@ -0,0 +1,159 @@ +#!/usr/bin/python + +import sys +from PyQt4.QtCore import * +from PyQt4.QtGui import * +import inspect + +GAP = 5 + +def clipVal(v, mn, mx): + if v < mn: return mn + if v > mx: return mx + return v + +class InnerCode(QWidget): + def __init__(self, scrollArea): + super().__init__(scrollArea) + self.scrollArea = scrollArea + self.setFont(QFont('Courier', 16)) + self.setFocusPolicy(Qt.StrongFocus) + self.blinkcursor = False + # Initial values: + self.setSource('') + self.CursorPosition = 0 + t = QTimer(self) + t.timeout.connect(self.updateCursor) + t.setInterval(500) + t.start() + def updateCursor(self): + self.blinkcursor = not self.blinkcursor + self.update(self.cursorX, self.cursorY, self.charWidth, self.charHeight) + def setSource(self, src): + self.src = src + self.adjust() + def setCursorPosition(self, c): + self.cursorPosition = clipVal(c, 0, len(self.src)) + print(self.cursorPosition, self.CursorRow, self.CursorCol) + self.cursorX = self.CursorCol * self.charWidth + self.xposTXT - self.charWidth + self.cursorY = self.CursorRow * self.charHeight - self.charHeight + CursorPosition = property(lambda self: self.cursorPosition, setCursorPosition) + @property + def CursorRow(self): + # TODO: make this nice. + txt = self.src[0:self.cursorPosition] + return len(txt.split('\n')) + @property + def CursorCol(self): + txt = self.src[0:self.cursorPosition] + curLine = txt.split('\n')[-1] + return len(curLine) + 1 + @property + def CurrentLine(self): + return self.getRow(self.CursorRow) + def getRow(self, r): + rows = self.src.split('\n') + r = r - 1 + if r < 0 or r > len(rows) - 1: + return '' + else: + return rows[r] + def getChar(self, pos): + pass + def insertText(self, txt): + self.setSource(self.src[0:self.CursorPosition] + txt + self.src[self.CursorPosition:]) + self.CursorPosition += len(txt) + def GotoNextChar(self): + if self.src[self.CursorPosition] != '\n': + self.CursorPosition += 1 + def GotoPrevChar(self): + if self.src[self.CursorPosition - 1] != '\n': + self.CursorPosition -= 1 + def GotoNextLine(self): + curLine = self.CurrentLine + c = self.CursorCol + self.CursorPosition += len(curLine) - c + c + 1 # line break char! + def GotoPrevLine(self): + curLine = self.CurrentLine + c = self.CursorCol + self.CursorPosition -= len(curLine) + c + 1 # line break char! + def paintEvent(self, event): + # Helper variables: + er = event.rect() + chw, chh = self.charWidth, self.charHeight + painter = QPainter(self) + # Background: + painter.fillRect(er, self.palette().color(QPalette.Base)) + painter.fillRect(QRect(self.xposLNA, er.top(), 8 * chw, er.bottom() + 1), Qt.gray) + painter.fillRect(self.xposTXT, (self.CursorRow - 1) * chh, er.width(), chh, Qt.yellow) + painter.setPen(Qt.gray) + # first and last row: + row1 = max(int(er.top() / chh) - 1, 0) + row2 = max(int(er.bottom() / chh) + 1, 0) + # Draw contents: + txt = self.src.split('\n') + print('update', row1, row2) + for row in range(row1, row2 + 1): + ypos = row * chh + painter.setPen(Qt.black) + painter.drawText(self.xposLNA, ypos, 'R ={0}'.format(row)) + xpos = self.xposTXT + if row - 1 < len(txt): + painter.drawText(xpos, ypos, txt[row - 1]) + # cursor + if self.blinkcursor: + painter.fillRect(self.cursorX, self.cursorY, 2, chh, Qt.black) + def keyPressEvent(self, event): + if event.matches(QKeySequence.MoveToNextChar): + self.GotoNextChar() + if event.matches(QKeySequence.MoveToPreviousChar): + self.GotoPrevChar() + if event.matches(QKeySequence.MoveToNextLine): + self.GotoNextLine() + if event.matches(QKeySequence.MoveToPreviousLine): + self.GotoPrevLine() + if event.matches(QKeySequence.MoveToNextPage): + for i in range(5): + self.GotoNextLine() + if event.matches(QKeySequence.MoveToPreviousPage): + for i in range(5): + self.GotoPrevLine() + if event.matches(QKeySequence.MoveToEndOfLine): + self.CursorPosition += len(self.CurrentLine) - self.CursorCol + 1 + if event.matches(QKeySequence.MoveToStartOfLine): + self.CursorPosition -= self.CursorCol - 1 + char = event.text().lower() + if char: + print('ins', char) + self.insertText(char) + self.update() + def adjust(self): + self.charHeight = self.fontMetrics().height() + self.charWidth = self.fontMetrics().width('x') + self.xposLNA = GAP + self.xposTXT = self.xposLNA + 8 * self.charWidth + GAP + self.xposEnd = self.xposTXT + self.charWidth * 80 + self.setMinimumWidth(self.xposEnd) + txt = self.src.split('\n') + self.setMinimumHeight(self.charHeight * len(txt)) + self.update() + +class CodeEdit(QScrollArea): + def __init__(self): + super().__init__() + self.ic = InnerCode(self) + self.setWidget(self.ic) + self.setWidgetResizable(True) + self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn) + self.setFocusPolicy(Qt.NoFocus) + Source = property(lambda s: s.ic.getSource(), lambda s, v: s.ic.setSource(v)) + +if __name__ == '__main__': + app = QApplication(sys.argv) + ce = CodeEdit() + ce.show() + src = ''.join(inspect.getsourcelines(InnerCode)[0]) + ce.Source = src + ce.resize(600, 500) + app.exec() +