[Interest] Performance problem in QTextDocument with many QTextCursors

Wilbert Berendsen wbsoft at xs4all.nl
Sat Dec 24 12:26:27 CET 2011


Hi,

I develop a (PyQt4) application where a QTextDocument is used with many
cursors. The cursors are used to keep track of short pieces (tokens) of
the text in the document.

(The application is Frescobaldi (www.frescobaldi.org), an editor to
edit music notation in LilyPond format. The objects in the
LilyPond-generated PDF are clicklable, and Frescobaldi connects them to
locations in the source text, because LilyPond puts filename, lineno
and column in the clickable urls. Frescobaldi connects them via
QTextCursors, so the connection remains correct while the user changes
the document. This works very good.)

But, as soon as the document grows a bit and has, say 1000 lines with
10000 cursors (corresponding to 10000 music notes), performance slows
down significantly, especially with operations that perform many small
changes (e.g. search/replace).

E.g. when I have 10000 cursors, each pointing to different words in the
text, and then I do a search/replace operation on, say, 1000 pieces of
text in the beginning, the operation can easily take more than 60
seconds on my (fast) machine.

Even if the replacements have the same length as the original texts,
and the cursors therefore don't change their positions, editing the
document becomes extremely slow.

Can I do anything to improve the speed? Or should I refrain from using
so many textcursors, and find a different means to keep track of tokens
in the text?.

Or could performance be slowed down somewhat by using the PyQt binding?

This is a short example of interactive Python code that shows the
problem:

python
from PyQt4.QtGui import *
ap=QApplication([])
e=QTextEdit()
e.show()
# now paste a blob of text in the edit, say, 20000 characters
d=e.document()

# create cursors
cs = [QTextCursor(d) for i in range(10000)]
for c in cs:
    c.setPosition(12345)

# (type in the text at the beginning, note the slowness)

# make 1000 replacements, takes extremely long time
c = QTextCursor(d)
for i in range(1000):
    c.setPosition(i*4)
    c.setPosition(i*4 + 3, QTextCursor.KeepAnchor)
    c.insertText('abc')

After deleting all the cursors in the list (del cs), the replace goes
much, much faster.

thanks for any further insight :)

-- 
Wilbert Berendsen
(http://www.wilbertberendsen.nl)




More information about the Interest mailing list