Posts: 26
Threads: 11
Joined: Apr 2022
Hi,
The following function is used to highlight text for a spell checker. If it finds a misspelt word it will underline it in red.
def highlightBlock(self, text: str) -> None:
if not hasattr(self, "speller"):
return
# The character format of text in a document specifies the visual properties of the text, as well as information about its role in a hypertext document.
self.misspelledFormat = QTextCharFormat()
self.misspelledFormat.setUnderlineStyle(
QTextCharFormat.SpellCheckUnderline) # we can set its visual style
self.misspelledFormat.setUnderlineColor(Qt.red) # red and underlined
# we iterate the text using the regular expression above which identifies word boundaries
for word_object in self.wordRegEx.finditer(text):
# we check to see if this is a recognised word
if not self.speller.check(word_object.group()):
self.setFormat( # if it is not we underline it using the style shown above
word_object.start(), # index of first letter of match
# index of last letter - index of first letter= length
word_object.end() - word_object.start(),
self.misspelledFormat,
) I am trying to figure out how I might do the opposite. For example:
Given a block of text in a QTextEdit object is there some way of determining the format attributes of that text. It is almost the opposite of QSyntaxHighlighter.setFormat() method. I want to be able to iterate through the block and find the underlined words or words highlighted in blue etc..
Posts: 6,780
Threads: 20
Joined: Feb 2020
Formatting text is done by inserting Markdown format tags in the text. You can get the text with the html tags using the QTextEdit.html attribute (assuming this is a QTextEdit object). This returns a str that you can parse to find all the formatting tags.
Posts: 1,027
Threads: 16
Joined: Dec 2016
If a "normal" selection would suffice, QTextEdit has a built-in find function.
Posts: 26
Threads: 11
Joined: Apr 2022
Thank you for your replies.
I had thought about the HTML approach, but I thought there had to be a more direct way of finding the format attributes. I found a post that suggested that using the HTML approach could be problematic because the format could be set outside the selection (i.e. stylesheets), and that the proper way to verify the format at a specified position is by getting the QTextCharFormat of the text cursor for a given character position.
def check_formatting(self):
# assume no format by default
bold = italic = underline = False
textCursor = self.textCursor()
rangeStart = textCursor.selectionStart()
if textCursor.hasSelection():
rangeEnd = textCursor.selectionEnd() + 1
else:
rangeEnd = textCursor.selectionStart() + 1
wordToCheck = textCursor.selectedText()
for pos in range(rangeStart, rangeEnd):
textCursor.setPosition(pos)
fmt = textCursor.charFormat()
underline = fmt.fontUnderline()
colour = fmt.underlineColor()
if fmt.fontWeight() >= QFont.Bold:
bold = True
if fmt.fontItalic():
italic = True
if fmt.fontUnderline():
underline = True
if all((bold, italic, underline)):
# all formats are set, no need for further checking
break This code was an attempt to do that, but when I run it I find that
underline = fmt.fontUnderline()
colour = fmt.underlineColor() underline is False and the Colour is #000000, even though the selected text, in this case, is underlined in red. I expected to see that reflected in underline and colour.
Posts: 1,027
Threads: 16
Joined: Dec 2016
Apr-17-2022, 06:56 PM
(This post was last modified: Apr-17-2022, 06:56 PM by Axel_Erfurt.)
This is a way to underline found text.
Press Return in the find field.
from PyQt5.QtCore import (QSize)
from PyQt5.QtGui import QIcon, QKeySequence, QTextCursor, QTextCharFormat
from PyQt5.QtWidgets import (QAction, QApplication, QMainWindow,
QTextEdit, QLineEdit)
from sys import argv, exit
class MainWindow(QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.setGeometry(50, 50, 800, 600)
self.windowList = []
self.myeditor = QTextEdit(""" Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.""")
self.myeditor.setAcceptRichText(False)
self.myeditor.setUndoRedoEnabled(True)
self.createActions()
self.createToolBars()
self.setWindowIcon(QIcon.fromTheme("accessories-text-editor"))
self.setCentralWidget(self.myeditor)
self.findfield.setFocus()
def createToolBars(self):
self.findToolBar = self.addToolBar("Suchen")
self.findToolBar.setIconSize(QSize(16, 16))
self.findfield = QLineEdit()
self.findfield.addAction(QIcon.fromTheme("edit-find"), 0)
self.findfield.setClearButtonEnabled(True)
self.findfield.setFixedWidth(200)
self.findfield.setPlaceholderText("suchen")
self.findfield.setStatusTip("press RETURN")
self.findfield.setText("ipsum")
self.findfield.returnPressed.connect(self.findText)
self.findToolBar.addWidget(self.findfield)
def createActions(self):
self.findAct = QAction(QIcon.fromTheme('edit-find'), "find", self,
shortcut=QKeySequence.Find, statusTip="find",
triggered=self.setFindText)
def setFindText(self):
self.findfield.setText(self.myeditor.textCursor().selectedText())
self.findText()
def findText(self):
fmt = QTextCharFormat()
fmt.setFontUnderline(False)
self.myeditor.selectAll()
self.myeditor.textCursor().mergeCharFormat(fmt)
self.myeditor.moveCursor (QTextCursor.Start)
fmt.setFontUnderline(True)
word = self.findfield.text()
while self.myeditor.find(word):
textcursor = self.myeditor.textCursor()
textcursor.select(QTextCursor.WordUnderCursor)
textcursor.mergeCharFormat(fmt)
self.myeditor.setTextCursor(textcursor)
if __name__ == '__main__':
app = QApplication(argv)
mainWin = MainWindow()
mainWin.show()
exit(app.exec_())
Posts: 26
Threads: 11
Joined: Apr 2022
Thank you @ Axel_Erfurt, but your code shows how one can find a particular word in a block of text and then underline it. I am trying to do the opposite. I am trying to scan through the existing text in a QTextEdit widget and find all words that have already been underlined.
Posts: 6,780
Threads: 20
Joined: Feb 2020
Quote:I had thought about the HTML approach, but I thought there had to be a more direct way of finding the format attributes. I found a post that suggested that using the HTML approach could be problematic because the format could be set outside the selection (i.e. stylesheets), and that the proper way to verify the format at a specified position is by getting the QTextCharFormat of the text cursor for a given character position
Does it matter what the formatting is? You are looking for isolated sections of text that has special formatting. This test will be surrounded by tags, in particular a tag to underline the text. Just search for tags that turn underlining on and off.
Posts: 26
Threads: 11
Joined: Apr 2022
Thanks @ deanhystad
I have reflected on the approach I am taking and the problem I am trying to solve and believe there is probably a more elegant way of doing what I am trying to do. My original idea was to use the formating information to derive the significance of certain text in the editor, for example: if a word was underlined in red it would denote that it was misspelt, but if it was underlined in blue it would indicate that it was grammatically wrong.
I do not think I should be using the syntax characters attributes as the identifier of certain properties pertaining to a word or a piece of text. I think instead I should be using metadata in the document itself, perhaps with something like QTextBlockUserData. So, I have begun to look in that direction now.
I appreciate you taking the time to answer my question though; it was helpful in making me reflect on what I wanted to do.
|