* QTextEdit With Line Numbers
Posted on August 15th, 2009 by John. Filed under programming.
Here is a Qt4 widget written in Python that allows for line numbers next to a QTextEdit. Similar to what is seen in a number of text editors such as gedit and kate.
from PyQt4.Qt import QFrame, QWidget, QTextEdit, QHBoxLayout, QPainter class LineTextWidget(QFrame): class NumberBar(QWidget): def __init__(self, *args): QWidget.__init__(self, *args) self.edit = None # This is used to update the width of the control. # It is the highest line that is currently visibile. self.highest_line = 0 def setTextEdit(self, edit): self.edit = edit def update(self, *args): ''' Updates the number bar to display the current set of numbers. Also, adjusts the width of the number bar if necessary. ''' # The + 4 is used to compensate for the current line being bold. width = self.fontMetrics().width(str(self.highest_line)) + 4 if self.width() != width: self.setFixedWidth(width) QWidget.update(self, *args) def paintEvent(self, event): contents_y = self.edit.verticalScrollBar().value() page_bottom = contents_y + self.edit.viewport().height() font_metrics = self.fontMetrics() current_block = self.edit.document().findBlock(self.edit.textCursor().position()) painter = QPainter(self) line_count = 0 # Iterate over all text blocks in the document. block = self.edit.document().begin() while block.isValid(): line_count += 1 # The top left position of the block in the document position = self.edit.document().documentLayout().blockBoundingRect(block).topLeft() # Check if the position of the block is out side of the visible # area. if position.y() > page_bottom: break # We want the line number for the selected line to be bold. bold = False if block == current_block: bold = True font = painter.font() 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. drawText(x, y, text). painter.drawText(self.width() - font_metrics.width(str(line_count)) - 3, round(position.y()) - contents_y + font_metrics.ascent(), str(line_count)) # Remove the bold style if it was set previously. if bold: font = painter.font() font.setBold(False) painter.setFont(font) block = block.next() self.highest_line = line_count painter.end() QWidget.paintEvent(self, event) def __init__(self, *args): QFrame.__init__(self, *args) self.setFrameStyle(QFrame.StyledPanel | QFrame.Sunken) self.edit = QTextEdit() self.edit.setFrameStyle(QFrame.NoFrame) self.edit.setAcceptRichText(False) self.number_bar = self.NumberBar() self.number_bar.setTextEdit(self.edit) hbox = QHBoxLayout(self) hbox.setSpacing(0) hbox.setMargin(0) hbox.addWidget(self.number_bar) hbox.addWidget(self.edit) self.edit.installEventFilter(self) self.edit.viewport().installEventFilter(self) def eventFilter(self, object, event): # Update the line numbers for all events on the text edit and the viewport. # This is easier than connecting all necessary singals. if object in (self.edit, self.edit.viewport()): self.number_bar.update() return False return QFrame.eventFilter(object, event) def getTextEdit(self): return self.edit
6 Responses to “QTextEdit With Line Numbers”
Leave a Reply
Tags
bash
batteries
bookeen
c++
calibre
cats
cover
cybook
device interfaces
ebook
electronics
epub
eReader
ezreader pocket pro
fb2
gadgets
GeR2
google
GUI
image
json
KDocker
kindle
Linux
markdown
mobi
N770
nook
palmdoc
pdb
pdf
pgm
pml
pmlz
pocket pro
pyqt
python
qt
rb
release
thumbnail
txt
x11
xlib
ztxt
Archives
- July 2010 (4)
- June 2010 (1)
- May 2010 (2)
- March 2010 (1)
- January 2010 (8)
- December 2009 (5)
- November 2009 (6)
- October 2009 (4)
- September 2009 (2)
- August 2009 (6)
- July 2009 (6)
- June 2009 (4)
- May 2009 (6)
- April 2009 (4)
- March 2009 (2)
- February 2009 (4)
- January 2009 (4)
- December 2008 (7)
- November 2008 (2)
October 10th, 2009 at 4:56 am
All code posted unless otherwise specified is licensed under the MIT License. This is compatible with your GPL3 project, just add the header at that link to the file. However, if you really don’t want MIT code in your project I’m okay with relicensing it under the GPL3 for use in your project. Again, just add the GPL3 header with attribution to me. Also, have a look at my Better QPlainTextEdit With Line Numbers because it fixes a few short comings of this one. If you have any questions about it and extending it feel free to ask.
October 10th, 2009 at 4:07 am
This TextEdit line numbering code is useful for me. There is no license mentioned. May I use it in a GPL3 project I am working on? Do you require attribution? Thanks!
October 10th, 2009 at 12:39 pm
Thanks. I tried the Better Line Numbers, but I am still running PyQt 4.4 and there is some code there that will not run (eg TextEdit.cursorPositionChanged). This one is doing exactly what I need. I appreciate your generous licensing.
November 5th, 2009 at 7:54 pm
Very impressive. It really must have taken some digging on your part figure out how to get the numbers to line up correctly.
I thank you and the artists at our studio who will be using this thank you.
PVC
June 5th, 2010 at 12:46 pm
Very nice code, exactly what I was looking for!
I slightly modified the code to fit my needs, eliminating the QFrame and using a QPlainTextEdit instead of a QTextEdit as base class of the editor. I published the modified code on my blog: http://www.japh.de/blog/qtextedit-with-line-numbers/
June 5th, 2010 at 12:58 pm
Andreas,
Take a look at http://john.nachtimwald.com/2009/08/19/better-qplaintextedit-with-line-numbers/ . It uses a QPlainTextEdit instead of the QTextEdit and adds a few things like highlighting of the current line. It still uses the QFrame… I do like your changes to eliminate the use of the QFrame.