Mercurial > lcfOS
comparison python/codeedit.py @ 249:e41e4109addd
Added current position arrow
author | Windel Bouwman |
---|---|
date | Fri, 26 Jul 2013 20:26:05 +0200 |
parents | b10d46e5c8dd |
children | f5fba5b554d7 |
comparison
equal
deleted
inserted
replaced
248:b10d46e5c8dd | 249:e41e4109addd |
---|---|
11 if v < mn: return mn | 11 if v < mn: return mn |
12 if v > mx: return mx | 12 if v > mx: return mx |
13 return v | 13 return v |
14 | 14 |
15 class InnerCode(QWidget): | 15 class InnerCode(QWidget): |
16 textChanged = pyqtSignal() | 16 textChanged = pyqtSignal() |
17 def __init__(self, scrollArea): | 17 def __init__(self, scrollArea): |
18 super().__init__(scrollArea) | 18 super().__init__(scrollArea) |
19 self.scrollArea = scrollArea | 19 self.scrollArea = scrollArea |
20 self.setFont(QFont('Courier', 12)) | 20 self.setFont(QFont('Courier', 12)) |
21 self.setFocusPolicy(Qt.StrongFocus) | 21 self.setFocusPolicy(Qt.StrongFocus) |
22 # TODO: only beam cursor in text area.. | 22 # TODO: only beam cursor in text area.. |
23 self.setCursor(Qt.IBeamCursor) | 23 self.setCursor(Qt.IBeamCursor) |
24 h = QFontMetrics(self.font()).height() | 24 h = QFontMetrics(self.font()).height() |
25 self.errorPixmap = QPixmap('icons/error.png').scaled(h, h) | 25 self.errorPixmap = QPixmap('icons/error.png').scaled(h, h) |
26 self.arrowPixmap = QPixmap('icons/arrow.png').scaled(h, h) | |
26 self.blinkcursor = False | 27 self.blinkcursor = False |
27 self.errorlist = [] | 28 self.errorlist = [] |
29 self.arrow = None | |
28 # Initial values: | 30 # Initial values: |
29 self.setSource('') | 31 self.setSource('') |
30 self.CursorPosition = 0 | 32 self.CursorPosition = 0 |
31 t = QTimer(self) | 33 t = QTimer(self) |
32 t.timeout.connect(self.updateCursor) | 34 t.timeout.connect(self.updateCursor) |
33 t.setInterval(500) | 35 t.setInterval(500) |
34 t.start() | 36 t.start() |
35 def updateCursor(self): | 37 def updateCursor(self): |
36 self.blinkcursor = not self.blinkcursor | 38 self.blinkcursor = not self.blinkcursor |
37 self.update() | 39 self.update() |
38 #self.update(self.cursorX, self.cursorY, self.charWidth, self.charHeight) | 40 #self.update(self.cursorX, self.cursorY, self.charWidth, self.charHeight) |
39 def setSource(self, src): | 41 |
42 def setSource(self, src): | |
40 self.src = src | 43 self.src = src |
41 self.adjust() | 44 self.adjust() |
42 def getSource(self): | 45 |
46 def getSource(self): | |
43 return self.src | 47 return self.src |
44 def setErrors(self, el): | 48 |
49 def setErrors(self, el): | |
45 self.errorlist = el | 50 self.errorlist = el |
46 self.update() | 51 self.update() |
47 def setCursorPosition(self, c): | 52 |
53 def setCursorPosition(self, c): | |
48 self.cursorPosition = clipVal(c, 0, len(self.src)) | 54 self.cursorPosition = clipVal(c, 0, len(self.src)) |
49 self.update() | 55 self.update() |
50 CursorPosition = property(lambda self: self.cursorPosition, setCursorPosition) | 56 |
51 @property | 57 CursorPosition = property(lambda self: self.cursorPosition, setCursorPosition) |
52 def Rows(self): | 58 |
53 # Make this nicer: | 59 @property |
54 return self.src.split('\n') | 60 def Rows(self): |
55 @property | 61 # Make this nicer: |
56 def CursorRow(self): | 62 return self.src.split('\n') |
57 # TODO: make this nice. | 63 |
58 txt = self.src[0:self.cursorPosition] | 64 @property |
59 return len(txt.split('\n')) | 65 def CursorRow(self): |
60 @property | 66 # TODO: make this nice. |
61 def CursorCol(self): | 67 txt = self.src[0:self.cursorPosition] |
62 txt = self.src[0:self.cursorPosition] | 68 return len(txt.split('\n')) |
63 curLine = txt.split('\n')[-1] | 69 |
64 return len(curLine) + 1 | 70 @property |
65 @property | 71 def CursorCol(self): |
66 def CurrentLine(self): | 72 txt = self.src[0:self.cursorPosition] |
67 return self.getRow(self.CursorRow) | 73 curLine = txt.split('\n')[-1] |
68 def setRowCol(self, r, c): | 74 return len(curLine) + 1 |
75 | |
76 @property | |
77 def CurrentLine(self): | |
78 return self.getRow(self.CursorRow) | |
79 | |
80 def setRowCol(self, r, c): | |
69 prevRows = self.Rows[:r-1] | 81 prevRows = self.Rows[:r-1] |
70 txt = '\n'.join(prevRows) | 82 txt = '\n'.join(prevRows) |
71 c = clipVal(c, 1, len(self.getRow(r))) | 83 c = clipVal(c, 1, len(self.getRow(r))) |
72 self.CursorPosition = len(txt) + c + 1 | 84 self.CursorPosition = len(txt) + c + 1 |
73 self.showRow(self.CursorRow) | 85 self.showRow(self.CursorRow) |
74 def getRow(self, r): | 86 |
87 def getRow(self, r): | |
75 rows = self.Rows | 88 rows = self.Rows |
76 r = r - 1 | 89 r = r - 1 |
77 if r < 0 or r > len(rows) - 1: | 90 if r < 0 or r > len(rows) - 1: |
78 return '' | 91 return '' |
79 else: | 92 else: |
80 return rows[r] | 93 return rows[r] |
81 def showRow(self, r): | 94 |
95 def showRow(self, r): | |
82 self.scrollArea.ensureVisible(self.xposTXT, r * self.charHeight, 4, self.charHeight) | 96 self.scrollArea.ensureVisible(self.xposTXT, r * self.charHeight, 4, self.charHeight) |
83 # Annotations: | 97 # Annotations: |
84 def addAnnotation(self, row, col, ln, msg): | 98 def addAnnotation(self, row, col, ln, msg): |
85 pass | 99 pass |
86 # Text modification: | 100 # Text modification: |
87 def getChar(self, pos): | 101 def getChar(self, pos): |
88 pass | 102 pass |
89 def insertText(self, txt): | 103 def insertText(self, txt): |
90 self.setSource(self.src[0:self.CursorPosition] + txt + self.src[self.CursorPosition:]) | 104 self.setSource(self.src[0:self.CursorPosition] + txt + self.src[self.CursorPosition:]) |
91 self.CursorPosition += len(txt) | 105 self.CursorPosition += len(txt) |
92 self.textChanged.emit() | 106 self.textChanged.emit() |
93 def deleteChar(self): | 107 def deleteChar(self): |
94 self.setSource(self.src[0:self.CursorPosition] + self.src[self.CursorPosition+1:]) | 108 self.setSource(self.src[0:self.CursorPosition] + self.src[self.CursorPosition+1:]) |
95 self.textChanged.emit() | 109 self.textChanged.emit() |
96 def GotoNextChar(self): | 110 def GotoNextChar(self): |
97 if self.src[self.CursorPosition] != '\n': | 111 if self.src[self.CursorPosition] != '\n': |
98 self.CursorPosition += 1 | 112 self.CursorPosition += 1 |
99 def GotoPrevChar(self): | 113 def GotoPrevChar(self): |
100 if self.src[self.CursorPosition - 1] != '\n': | 114 if self.src[self.CursorPosition - 1] != '\n': |
101 self.CursorPosition -= 1 | 115 self.CursorPosition -= 1 |
102 def GotoNextLine(self): | 116 def GotoNextLine(self): |
103 curLine = self.CurrentLine | 117 curLine = self.CurrentLine |
104 c = self.CursorCol - 1 # go to zero based | 118 c = self.CursorCol - 1 # go to zero based |
105 self.CursorPosition += len(curLine) - c + 1 # line break char! | 119 self.CursorPosition += len(curLine) - c + 1 # line break char! |
106 curLine = self.CurrentLine | 120 curLine = self.CurrentLine |
107 if len(curLine) < c: | 121 if len(curLine) < c: |
108 self.CursorPosition += len(curLine) | 122 self.CursorPosition += len(curLine) |
109 else: | 123 else: |
110 self.CursorPosition += c | 124 self.CursorPosition += c |
111 self.showRow(self.CursorRow) | 125 self.showRow(self.CursorRow) |
112 def GotoPrevLine(self): | 126 def GotoPrevLine(self): |
113 c = self.CursorCol - 1 # go to zero based | 127 c = self.CursorCol - 1 # go to zero based |
114 self.CursorPosition -= c + 1 # line break char! | 128 self.CursorPosition -= c + 1 # line break char! |
115 curLine = self.CurrentLine | 129 curLine = self.CurrentLine |
116 if len(curLine) > c: | 130 if len(curLine) > c: |
117 self.CursorPosition -= len(curLine) - c | 131 self.CursorPosition -= len(curLine) - c |
118 self.showRow(self.CursorRow) | 132 self.showRow(self.CursorRow) |
119 def paintEvent(self, event): | 133 def paintEvent(self, event): |
120 # Helper variables: | 134 # Helper variables: |
121 er = event.rect() | 135 er = event.rect() |
122 chw, chh = self.charWidth, self.charHeight | 136 chw, chh = self.charWidth, self.charHeight |
123 painter = QPainter(self) | 137 painter = QPainter(self) |
124 # Background: | 138 # Background: |
142 painter.fillRect(cursorX, cursorY, 2, chh, Qt.black) | 156 painter.fillRect(cursorX, cursorY, 2, chh, Qt.black) |
143 painter.setPen(Qt.black) | 157 painter.setPen(Qt.black) |
144 painter.drawText(self.xposLNA, ypos, '{0}'.format(row)) | 158 painter.drawText(self.xposLNA, ypos, '{0}'.format(row)) |
145 xpos = self.xposTXT | 159 xpos = self.xposTXT |
146 painter.drawText(xpos, ypos, self.getRow(row)) | 160 painter.drawText(xpos, ypos, self.getRow(row)) |
161 if self.arrow and self.arrow.row == row: | |
162 painter.drawPixmap(self.xposERR, ypos + ydt, self.arrowPixmap) | |
147 curErrors = [e for e in self.errorlist if e.loc.row == row] | 163 curErrors = [e for e in self.errorlist if e.loc.row == row] |
148 for e in curErrors: | 164 for e in curErrors: |
149 painter.drawPixmap(self.xposERR, ypos + ydt, self.errorPixmap) | 165 painter.drawPixmap(self.xposERR, ypos + ydt, self.errorPixmap) |
150 painter.setPen(errorPen) | 166 painter.setPen(errorPen) |
151 x = self.xposTXT + (e.loc.col - 1) * chw - 2 | 167 x = self.xposTXT + (e.loc.col - 1) * chw - 2 |
155 #painter.drawRoundedRect(x, ypos + ydt, wt, chh, 7, 7) | 171 #painter.drawRoundedRect(x, ypos + ydt, wt, chh, 7, 7) |
156 # print error balloon | 172 # print error balloon |
157 #painter.drawText(x, ypos + chh, e.msg) | 173 #painter.drawText(x, ypos + chh, e.msg) |
158 #if len(curErrors) > 0: | 174 #if len(curErrors) > 0: |
159 # ypos += chh | 175 # ypos += chh |
160 | |
161 ypos += chh | 176 ypos += chh |
162 def keyPressEvent(self, event): | 177 |
178 def keyPressEvent(self, event): | |
163 if event.matches(QKeySequence.MoveToNextChar): | 179 if event.matches(QKeySequence.MoveToNextChar): |
164 self.GotoNextChar() | 180 self.GotoNextChar() |
165 elif event.matches(QKeySequence.MoveToPreviousChar): | 181 elif event.matches(QKeySequence.MoveToPreviousChar): |
166 self.GotoPrevChar() | 182 self.GotoPrevChar() |
167 elif event.matches(QKeySequence.MoveToNextLine): | 183 elif event.matches(QKeySequence.MoveToNextLine): |
188 else: | 204 else: |
189 char = event.text() | 205 char = event.text() |
190 if char: | 206 if char: |
191 self.insertText(char) | 207 self.insertText(char) |
192 self.update() | 208 self.update() |
193 def mousePressEvent(self, event): | 209 |
210 def mousePressEvent(self, event): | |
194 pos = event.pos() | 211 pos = event.pos() |
195 if pos.x() > self.xposTXT and pos.x(): | 212 if pos.x() > self.xposTXT and pos.x(): |
196 c = round((pos.x() - self.xposTXT) / self.charWidth) | 213 c = round((pos.x() - self.xposTXT) / self.charWidth) |
197 r = int(pos.y() / self.charHeight) + 1 | 214 r = int(pos.y() / self.charHeight) + 1 |
198 self.setRowCol(r, c) | 215 self.setRowCol(r, c) |
199 def adjust(self): | 216 |
217 def adjust(self): | |
200 metrics = self.fontMetrics() | 218 metrics = self.fontMetrics() |
201 self.charHeight = metrics.height() | 219 self.charHeight = metrics.height() |
202 self.charWidth = metrics.width('x') | 220 self.charWidth = metrics.width('x') |
203 self.charDescent = metrics.descent() | 221 self.charDescent = metrics.descent() |
204 self.xposERR = GAP | 222 self.xposERR = GAP |
221 self.setFocusPolicy(Qt.NoFocus) | 239 self.setFocusPolicy(Qt.NoFocus) |
222 self.showRow = self.ic.showRow | 240 self.showRow = self.ic.showRow |
223 self.setRowCol = self.ic.setRowCol | 241 self.setRowCol = self.ic.setRowCol |
224 self.FileName = None | 242 self.FileName = None |
225 Source = property(lambda s: s.ic.getSource(), lambda s, v: s.ic.setSource(v)) | 243 Source = property(lambda s: s.ic.getSource(), lambda s, v: s.ic.setSource(v)) |
244 | |
226 def setErrors(self, el): | 245 def setErrors(self, el): |
227 self.ic.setErrors(el) | 246 self.ic.setErrors(el) |
228 | 247 |
229 def setFocus(self): | 248 def setFocus(self): |
230 self.ic.setFocus() | 249 self.ic.setFocus() |
232 def setFileName(self, fn): | 251 def setFileName(self, fn): |
233 self.filename = fn | 252 self.filename = fn |
234 if not fn: | 253 if not fn: |
235 fn = 'Untitled' | 254 fn = 'Untitled' |
236 self.setWindowTitle(fn) | 255 self.setWindowTitle(fn) |
256 | |
237 def getFileName(self): | 257 def getFileName(self): |
238 return self.filename | 258 return self.filename |
239 FileName = property(getFileName, setFileName) | 259 FileName = property(getFileName, setFileName) |
240 | 260 |
241 | 261 |
242 if __name__ == '__main__': | 262 if __name__ == '__main__': |
243 app = QApplication(sys.argv) | 263 app = QApplication(sys.argv) |
244 ce = CodeEdit() | 264 ce = CodeEdit() |
245 ce.show() | 265 ce.show() |
246 src = ''.join(inspect.getsourcelines(InnerCode)[0]) | 266 src = ''.join(inspect.getsourcelines(InnerCode)[0]) |
247 ce.Source = src | 267 ce.Source = src |
248 print(ce.Source) | 268 ce.resize(600, 800) |
249 ce.resize(600, 800) | 269 app.exec() |
250 app.exec() | 270 |
251 |