Source code for usdmanager.linenumbers

#
# Copyright 2018 DreamWorks Animation L.L.C.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
"""
Line numbers widget for optimized display of line numbers on the left side of
a text widget.
"""
from Qt.QtCore import Slot
from Qt.QtWidgets import QFrame, QWidget
from Qt.QtGui import QFont, QPainter, QTextCharFormat


[docs]class LineNumbers(QWidget): """ Line number widget for `QTextBrowser` and `QTextEdit` widgets. Currently does not support `QPlainTextEdit` widgets. """ def __init__(self, *args, **kwargs): super(LineNumbers, self).__init__(*args) self.textWidget = self.doc = None self.setTextWidget(kwargs.pop('widget', None)) # Monospaced font to keep width from shifting. font = QFont() font.setStyleHint(QFont.Courier) font.setFamily("Monospace") self.setFont(font) self.updateAndResize()
[docs] def connectSignals(self): """ Connect relevant `QTextBrowser` or `QTextEdit` signals. """ self.textWidget.verticalScrollBar().valueChanged[int].connect(self.update) self.textWidget.currentCharFormatChanged[QTextCharFormat].connect(self.updateAndResize) self.textWidget.cursorPositionChanged.connect(self.update) self.textWidget.selectionChanged.connect(self.update) self.doc.blockCountChanged[int].connect(self.updateAndResize)
[docs] def setTextWidget(self, widget): """ Set the current text widget. :Parameters: widget : `QTextBrowser` | `QTextEdit` The text widget that uses a QTextDocument """ if widget is None: return self.textWidget = widget self.doc = self.textWidget.document() self.connectSignals()
[docs] @Slot() @Slot(int) def update(self, *args): """ Just update. We know we don't need to resize with the signals that call this method. """ super(LineNumbers, self).update()
[docs] @Slot(int) @Slot(QTextCharFormat) def updateAndResize(self, *args): """ Resize bar if needed. """ width = self.fontMetrics().width(str(self.doc.blockCount())) + 5 if self.width() != width: self.setFixedWidth(width) super(LineNumbers, self).update()
[docs] def paintEvent(self, event): """ Override the default paintEvent to add in line numbers. """ vScrollPos = self.textWidget.verticalScrollBar().value() pageBtm = vScrollPos + self.textWidget.viewport().height() currBlock = self.doc.findBlock(self.textWidget.textCursor().position()) fontMetric = self.fontMetrics() painter = QPainter(self) font = painter.font() # Find roughly the current top-most visible block. block = self.doc.begin() lineHeight = self.doc.documentLayout().blockBoundingRect(block).height() block = self.doc.findBlockByNumber(int(vScrollPos/lineHeight)) currLine = block.blockNumber() while block.isValid(): currLine += 1 # Check if the position of the block is outside the visible area. yPos = self.doc.documentLayout().blockBoundingRect(block).topLeft().y() if yPos > pageBtm: break if block == currBlock: # Make the line number for the selected line bold. font.setBold(True) painter.setFont(font) # Draw the line number right justified at the y position of the line. 3 is a magic padding number. painter.drawText(self.width() - fontMetric.width(str(currLine)) - 3, round(yPos) - vScrollPos + fontMetric.ascent() + 3, str(currLine)) font.setBold(False) painter.setFont(font) else: painter.drawText(self.width() - fontMetric.width(str(currLine)) - 3, round(yPos) - vScrollPos + fontMetric.ascent() + 3, str(currLine)) # Go to the next block. block = block.next() painter.end() super(LineNumbers, self).paintEvent(event)