| | from PySide.QtWidgets import QWidget, QPlainTextEdit |
| | from PySide.QtGui import QPainter, QFont |
| | from PySide.QtCore import Qt, QRect, QSize |
| |
|
| |
|
| | class LineNumberArea(QWidget): |
| | def __init__(self, editor): |
| | super().__init__(editor) |
| | self.editor = editor |
| |
|
| | def sizeHint(self): |
| | return QSize(self.editor.fontMetrics().horizontalAdvance("999") + 4, 0) |
| |
|
| | def paintEvent(self, event): |
| | painter = QPainter(self) |
| | painter.fillRect(event.rect(), Qt.black) |
| | font = QFont() |
| | font.setFamily(self.editor.font().family()) |
| | font.setFixedPitch(self.editor.font().fixedPitch()) |
| | font.setPointSize(self.editor.font().pointSize()) |
| | painter.setFont(font) |
| |
|
| | block = self.editor.firstVisibleBlock() |
| | blockNumber = block.blockNumber() |
| | top = self.editor.blockBoundingGeometry(block).translated(self.editor.contentOffset()).top() |
| | bottom = top + self.editor.blockBoundingRect(block).height() |
| |
|
| | while block.isValid() and top <= event.rect().bottom(): |
| | if block.isVisible() and bottom >= event.rect().top(): |
| | number = str(blockNumber + 1) |
| | painter.setPen(Qt.gray) |
| | painter.drawText( |
| | -6, |
| | int(top), |
| | self.width(), |
| | self.editor.fontMetrics().height(), |
| | Qt.AlignRight, |
| | number, |
| | ) |
| |
|
| | block = block.next() |
| | top = bottom |
| | bottom = top + self.editor.blockBoundingRect(block).height() |
| | blockNumber += 1 |
| |
|
| |
|
| | class CodeEditor(QPlainTextEdit): |
| | def __init__(self, parent=None): |
| | super().__init__(parent) |
| | self.lineNumberArea = LineNumberArea(self) |
| | self.blockCountChanged.connect(self.updateLineNumberAreaWidth) |
| | self.updateRequest.connect(self.updateLineNumberArea) |
| | self.verticalScrollBar().valueChanged.connect(self.lineNumberArea.update) |
| |
|
| | self.updateLineNumberAreaWidth(0) |
| |
|
| | def lineNumberAreaWidth(self): |
| | digits = 2 |
| | max_value = max(1, self.blockCount()) |
| | while max_value >= 10: |
| | max_value /= 10 |
| | digits += 1 |
| | space = 3 + self.fontMetrics().horizontalAdvance("9") * digits |
| | return space |
| |
|
| | def updateLineNumberAreaWidth(self, newBlockCount): |
| | self.setViewportMargins(self.lineNumberAreaWidth(), 0, 0, 0) |
| |
|
| | def updateLineNumberArea(self, rect, dy): |
| | if dy: |
| | self.lineNumberArea.scroll(0, dy) |
| | else: |
| | self.lineNumberArea.update(0, rect.y(), self.lineNumberArea.width(), rect.height()) |
| |
|
| | if rect.contains(self.viewport().rect()): |
| | self.updateLineNumberAreaWidth(0) |
| |
|
| | def resizeEvent(self, event): |
| | super().resizeEvent(event) |
| | cr = self.contentsRect() |
| | self.lineNumberArea.setGeometry( |
| | QRect(cr.left(), cr.top(), self.lineNumberAreaWidth(), cr.height()) |
| | ) |
| |
|
| | def setText(self, text): |
| | """Backward compatibility method for setText() calls.""" |
| | self.setPlainText(text) |
| |
|