comparison python/codeeditor.py @ 97:5a965e9664f2

Movage
author windel
date Mon, 24 Dec 2012 13:32:54 +0100
parents python/libs/widgets/codeeditor.py@4a27c28c7d0f
children fe145e42259d
comparison
equal deleted inserted replaced
96:a350055d6119 97:5a965e9664f2
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