Mercurial > lcfOS
comparison python/libs/widgets/codeeditor.py @ 64:4a27c28c7d0f
File movage
author | windel |
---|---|
date | Sun, 07 Oct 2012 17:13:47 +0200 |
parents | python/apps/ide/codeeditor.py@32078200cdd6 |
children |
comparison
equal
deleted
inserted
replaced
63:32078200cdd6 | 64:4a27c28c7d0f |
---|---|
1 from PyQt4.QtCore import * | |
2 from PyQt4.QtGui import * | |
3 import compiler.lexer | |
4 import os.path | |
5 | |
6 class MySyntaxHighlighter(QSyntaxHighlighter): | |
7 def __init__(self, parent=None): | |
8 super(MySyntaxHighlighter, self).__init__(parent) | |
9 # Syntax highlighting: | |
10 self.rules = [] | |
11 fmt = QTextCharFormat() | |
12 fmt.setForeground(Qt.darkBlue) | |
13 fmt.setFontWeight(QFont.Bold) | |
14 for kw in compiler.lexer.keywords: | |
15 pattern = '\\b'+kw+'\\b' | |
16 self.rules.append( (pattern, fmt) ) | |
17 | |
18 # Comments: | |
19 fmt = QTextCharFormat() | |
20 fmt.setForeground(Qt.gray) | |
21 fmt.setFontItalic(True) | |
22 pattern = '\{.*\}' | |
23 self.rules.append( (pattern, fmt) ) | |
24 | |
25 # Procedure: | |
26 fmt = QTextCharFormat() | |
27 fmt.setForeground(Qt.blue) | |
28 fmt.setFontItalic(True) | |
29 #pattern = '(?<=procedure )[A-Za-z]' | |
30 # TODO lookbehind does not work, think something else | |
31 #self.rules.append( (pattern, fmt) ) | |
32 | |
33 def highlightBlock(self, text): | |
34 for pattern, fmt in self.rules: | |
35 expression = QRegExp(pattern) | |
36 index = expression.indexIn(text) | |
37 while index >= 0: | |
38 length = expression.matchedLength() | |
39 self.setFormat(index, length, fmt) | |
40 index = expression.indexIn(text, index + length) | |
41 | |
42 class LineNumberArea(QWidget): | |
43 def __init__(self, codeedit): | |
44 super(LineNumberArea, self).__init__(codeedit) | |
45 self.codeedit = codeedit | |
46 # TODO: display error in this: self.setToolTip('hello world') | |
47 def sizeHint(self): | |
48 return QSize(self.codeedit.lineNumberAreaWidth(), 0) | |
49 def paintEvent(self, ev): | |
50 self.codeedit.lineNumberAreaPaintEvent(ev) | |
51 | |
52 class CodeEdit(QPlainTextEdit): | |
53 def __init__(self, parent=None): | |
54 super(CodeEdit, self).__init__(parent) | |
55 # members: | |
56 self.isUntitled = True | |
57 self.filename = None | |
58 self.setFont(QFont('Courier')) | |
59 self.lineNumberArea = LineNumberArea(self) | |
60 | |
61 self.blockCountChanged.connect(self.updateLineNumberAreaWidth) | |
62 self.updateRequest.connect(self.updateLineNumberArea) | |
63 | |
64 # Syntax highlighter: | |
65 self.highlighter = MySyntaxHighlighter(self.document()) | |
66 | |
67 def setFileName(self, filename): | |
68 self.filename = filename | |
69 self.isUntitled = False | |
70 self.setWindowTitle(filename) | |
71 def setSource(self, source): | |
72 self.setPlainText(source) | |
73 | |
74 def save(self): | |
75 pass | |
76 def saveAs(self): | |
77 pass | |
78 | |
79 def saveFile(self): | |
80 if self.isUntitled: | |
81 self.saveAs() | |
82 else: | |
83 source = str(self.toPlainText()) | |
84 f = open(self.filename, 'w') | |
85 f.write(source) | |
86 f.close() | |
87 | |
88 def highlightErrorLocation(self, row, col): | |
89 tc = QTextCursor(self.document()) | |
90 tc.clearSelection() | |
91 tc.movePosition(tc.Down, tc.MoveAnchor, row - 1) | |
92 tc.movePosition(tc.Right, tc.MoveAnchor, col - 1) | |
93 tc.movePosition(tc.NextCharacter, tc.KeepAnchor) # Select 1 character | |
94 selection = QTextEdit.ExtraSelection() | |
95 lineColor = QColor(Qt.red).lighter(160) | |
96 selection.format.setBackground(lineColor) | |
97 #selection.format.setProperty(QTextFormat.FullWidthSelection, True) | |
98 selection.cursor = tc | |
99 self.setExtraSelections( [ selection ] ) | |
100 def clearErrors(self): | |
101 self.setExtraSelections( [ ] ) | |
102 | |
103 def lineNumberAreaWidth(self): | |
104 digits = 1 | |
105 mx = max(1, self.blockCount()) | |
106 while mx >= 10: | |
107 mx = mx / 10 | |
108 digits += 1 | |
109 space = 3 + self.fontMetrics().width('8') * digits | |
110 return space | |
111 def lineNumberAreaPaintEvent(self, ev): | |
112 painter = QPainter(self.lineNumberArea) | |
113 painter.fillRect(ev.rect(), Qt.lightGray) | |
114 block = self.firstVisibleBlock() | |
115 blockNumber = block.blockNumber() | |
116 top = self.blockBoundingGeometry(block).translated(self.contentOffset()).top() | |
117 bottom = top + self.blockBoundingRect(block).height() | |
118 while block.isValid() and top <= ev.rect().bottom(): | |
119 if block.isVisible() and bottom >= ev.rect().top(): | |
120 num = str(blockNumber + 1) | |
121 painter.setPen(Qt.black) | |
122 painter.drawText(0, top, self.lineNumberArea.width(), self.fontMetrics().height(), Qt.AlignRight, num) | |
123 block = block.next() | |
124 top = bottom | |
125 bottom = top + self.blockBoundingRect(block).height() | |
126 blockNumber += 1 | |
127 def resizeEvent(self, ev): | |
128 super(CodeEdit, self).resizeEvent(ev) | |
129 cr = self.contentsRect() | |
130 self.lineNumberArea.setGeometry(QRect(cr.left(), cr.top(), self.lineNumberAreaWidth(), cr.height() )) | |
131 def updateLineNumberAreaWidth(self, newBlockCount): | |
132 self.setViewportMargins(self.lineNumberAreaWidth(), 0, 0, 0) | |
133 def updateLineNumberArea(self, rect, dy): | |
134 if dy > 0: | |
135 self.lineNumberArea.scroll(0, dy) | |
136 else: | |
137 self.lineNumberArea.update(0, rect.y(), self.lineNumberArea.width(), rect.height()) | |
138 if rect.contains(self.viewport().rect()): | |
139 self.updateLineNumberAreaWidth(0) | |
140 |