QTextDocument-Line-ending-and-Advanced-regular-expression-support: Difference between revisions

From Qt Wiki
Jump to navigation Jump to search
No edit summary
 
No edit summary
Line 1: Line 1:
=QTextDocument Line Endings and Advanced RegExp=
h1. QTextDocument Line Endings and Advanced RegExp


==Warning: Experimental Info==
== Warning: Experimental Info ==


I’ve picked from QtForum itself. It’s progressive article. I will update more when I will achieve something.
I've picked from QtForum itself. It's progressive article. I will update more when I will achieve something.


The find(regex) method of QTextDocument will not attempt to match across a “block” boundary (see answers in this post [developer.qt.nokia.com]). As a result, although the QRegExp doc says that \n is matched by .* and by \s, one can never get a match to \n in a QPlainTextEdit document. The \n is end of block and the search never spans a block. Thus it seems impossible for a pattern like
The find(regex) method of QTextDocument will not attempt to match across a “block” boundary (see answers in this post [developer.qt.nokia.com]). As a result, although the QRegExp doc says that is matched by .* and by , one can never get a match to in a QPlainTextEdit document. The is end of block and the search never spans a block. Thus it seems impossible for a pattern like
 
<code>&lt;b&amp;gt;.*&lt;/b&amp;gt;<code>


to find a match when the markup begins on one line and ends on another.
to find a match when the markup begins on one line and ends on another.


There is a way around this. The restriction is in QTextDocument; QRegExp does perform as documented when it is applied to a QString. So the following code can apply a general regex to a document. This is using PyQt4; the translation to C++ should be clear. Given is a QPlainTextEdit qpte whose cursor is the starting point for the search. Also given is a QRegExp qrxp that has been prepared with a search pattern such as “&lt;b&gt;.*&lt;/b&gt;” and its minimal and case switches set.
There is a way around this. The restriction is in QTextDocument; QRegExp does perform as documented when it is applied to a QString. So the following code can apply a general regex to a document. This is using PyQt4; the translation to C++ should be clear. Given is a QPlainTextEdit qpte whose cursor is the starting point for the search. Also given is a QRegExp qrxp that has been prepared with a search pattern such as “&lt;b&amp;gt;.*&lt;/b&amp;gt;” and its minimal and case switches set.


There remains one restriction: QTextCursor.selectedText() returns a string in which the \n character has been replaced with Unicode paragraph separator. This character does match to \s and .* however to match a literal \n you have to change the pattern given to the regexp, replacing all \n with \x2029.
</code><br /> start_tc = qpte.textCursor() # cursor with starting position<br /> range_tc = QTextCursor(start_tc) # make a copy linked to same doc<br /> range_tc.movePosition(QTextCursor.End) # point to end of doc<br /> # set cursor to select all text from starting point to end<br /> range_tc.setPosition(start_tc.selectionStart(),QTextCursor.KeepAnchor)<br /> # apply regexp to (part of) the document as a QString<br /> hit_pos = qrxp.indexIn(range_tc.selectedText())<br /> if hit_pos &gt; –1 : # first occurrence at hit_pos offset<br /> find_tc = QTextCursor(start_tc) # another cursor<br /> find_tc.setPosition(start_tc.selectionStart()+hit_pos) # point to hit<br /> find_tc.movePosition(QTextCursor.Right,<br /> QTextCursor.KeepAnchor,<br /> qrxp.matchedLength()) # select matched text<br /> qpte.setTextCursor(find_tc) # match visible to user<code>

Revision as of 11:13, 24 February 2015

h1. QTextDocument Line Endings and Advanced RegExp

Warning: Experimental Info

I've picked from QtForum itself. It's progressive article. I will update more when I will achieve something.

The find(regex) method of QTextDocument will not attempt to match across a “block” boundary (see answers in this post [developer.qt.nokia.com]). As a result, although the QRegExp doc says that is matched by .* and by , one can never get a match to in a QPlainTextEdit document. The is end of block and the search never spans a block. Thus it seems impossible for a pattern like

&lt;b&amp;gt;.*&lt;/b&amp;gt;<code>

to find a match when the markup begins on one line and ends on another.

There is a way around this. The restriction is in QTextDocument; QRegExp does perform as documented when it is applied to a QString. So the following code can apply a general regex to a document. This is using PyQt4; the translation to C++ should be clear. Given is a QPlainTextEdit qpte whose cursor is the starting point for the search. Also given is a QRegExp qrxp that has been prepared with a search pattern such as &lt;b&amp;gt;.*&lt;/b&amp;gt; and its minimal and case switches set.


start_tc = qpte.textCursor() # cursor with starting position
range_tc = QTextCursor(start_tc) # make a copy linked to same doc
range_tc.movePosition(QTextCursor.End) # point to end of doc
# set cursor to select all text from starting point to end
range_tc.setPosition(start_tc.selectionStart(),QTextCursor.KeepAnchor)
# apply regexp to (part of) the document as a QString
hit_pos = qrxp.indexIn(range_tc.selectedText())
if hit_pos > –1 : # first occurrence at hit_pos offset
find_tc = QTextCursor(start_tc) # another cursor
find_tc.setPosition(start_tc.selectionStart()+hit_pos) # point to hit
find_tc.movePosition(QTextCursor.Right,
QTextCursor.KeepAnchor,
qrxp.matchedLength()) # select matched text
qpte.setTextCursor(find_tc) # match visible to user