How to fast append to QTextEdit - c++

I have an application that has some sort of log viewer, that needs to be able to render formatted log records that are inserted to it in real time.
I am writing this in Qt and so far I was using QTextEdit for rendering of the text, which was beautified using some html tags and later inserted either with setHtml or insertHtml.
The problem is however, that these functions are insanely CPU intensive and run for ages, hanging whole application.
A similar question was asked here: QTextEdit.insertHtml() is very slow
Apart it has no really useful answer, other than stating it's really slow, it actually asks a different thing. I don't need to speed up setHtml or insertHtml. I am willing to use entirely different technique if possible.
Is there any mechanism within Qt that would allow for really fast insertions of text? Or maybe even completely different component than QTextEdit?
Is there any way to append new line to QTextEdit which contains rich text (generated in any way) that is really fast?
I also noticed QTextBrowser but it seems to be just an extension of TextEdit, could it be faster?

You should give QPlainTextEdit a try. It uses the same technology as QTextEdit but is a lot faster. It is optimized for plain text handling but do not let that fool you, it still has some basic support for formatting using HTML. You can append HTML formatted text with appendHtml().

In my application, I also need to display a large log of the task, approximately 3500 lines. Some lines of the log should be colored. For this, I used HTML formatting. QTextEdit.setHtml with this amount of text, freezed my GUI.
I replaced QTextEdit with QListWidget, in which QListWidgetItem is created for each line of the log.
It began to work much faster, without friezes.
And I saved colored text, just simple by using the QListWidgetItem.setForeground.

[This post][1]
[1]: Performantly appending (rich) text to QTextEdit or QTextBrowser in Qt contains an answer to this problem. The gist: instead of simply appending an HTML snippet, manipulate the underlying document directly.
However, I suggest that if your display really is a list of single lines, you create a QAbstractListModel QAbstractTableModel derived class instead and show it in an item view.

Related

MFC: what is the best way to generate and display large document?

I am still new to this area. My current project requires to generate and display large report (over a few hundred pages). The structure of document is quite simple but still contains row-column formatting with a few colors, fonts and lines. Also, it needs to be printable which is quite a headache. The approach I am taking is to use browser control plus HTML. One issue is that when the document gets big, UI is pretty lagging. Is there other way of doing that?

Multiple visual text cursors in QPlainTextEdit

In Sublime Text, if you hold control while clicking, you can add another cursor to the document, allowing you to type and edit in multiple places at once. I'm trying to recreate this with Qt's QPlainTextEdit. The logic seems pretty simple...
On Ctrl+click, create and store a new cursor at location of the click
Draw all cursors
When any key events happen, make sure the other cursors also receive them
However, it seems that in order to do these things, I have to understand exactly how QPlainTextEdit works, and while I have a loose understanding, I find the source to be very dense and difficult to navigate.
While this feature is very important to me, I can't afford to spend a month on it. I don't know how to reasonably proceed. Is there some open source text editor built with Qt that has this feature? Can I in fact implement it without thoroughly understanding how QPlainTextEdit works? Is there some other solution I have not considered? I thought this would be trivial, or at the very least someone might have solved it before, but that doesn't appear to be the case. Any advice is appreciated.
Is there some open source text editor built with Qt that has this feature?
QtCreator is open-source (source code) and has partial multiple-cursor functionality. While it does not support Ctrl+Click to add a new cursor, you can do Shift+Alt+DownArrow to add a cursor to the following line (same column), like in SublimeText, and then insert text to all the lines at once.
It seems implemented in their class TextEditorWidget, which inherits QPlainTextEdit and reimplements plenty of its virtual methods. I don't exactly know how they implemented the multi-cursor functionality, but probably looking at the code of TextEditorWidget can give hints.
However, keep in mind that QtCreator does not have full multi-cursor functionality like in Sublime Text or CLion: the mutliple cursors are necessarily in the same column, and you cannot move the multiple cursors left/right. For example something I often do in Sublime is multiple selection at the beginning of lines, followed by Ctrl+RightArrow to jump all cursors "one word to the right". You cannot do that in QtCreator as of August 2020.
There is an open feature request for having true multiple-cursor functionality in QtCreator:
https://bugreports.qt.io/browse/QTCREATORBUG-16013
However, it seems that in order to do these things, I have to
understand exactly how QPlainTextEdit works, and while I have a loose
understanding, I find the source to be very dense and difficult to
navigate.
To some extent, but not a lot. Once you get the cursor positions, you know the positions in the document where text needs to be inserted. QTextEdit already supports multiple cursor positions:
https://doc.qt.io/qt-5/richtext-cursor.html
Rich text documents can have multiple cursors associated with them,
and each of these contains information about their position in the
document and any selections that they may hold. This cursor-based
paradigm makes common operations, such as cutting and pasting text,
simple to implement programmatically, yet it also allows more complex
editing operations to be performed on the document.
and
Multiple Cursors
Multiple cursors can be used to simultaneously edit the same document,
although only one will be visible to the user in a QTextEdit widget.
The QTextDocument ensures that each cursor writes text correctly and
does not interfere with any of the others.
Since this feature already exists, it may not be as difficult as thought to read the documentation and implement the feature.
As QPlainTextEdit is implemented by using most of the tech behind QTextEdit and QTextDocument, maybe it will meet your requirements.

QTextEdit vs QPlainTextEdit

What's the difference between QTextEdit and QPlainTextEdit, why use one over the other?
I'm coding a text editor as an exercice to learn Qt5, and now I'm wondering whether to use QTextEdit or QPlainTextEdit.
So far I've only found out that you can display images in QTextEdit, but other than that they look somewhat identical to me.
My text editor should support some basic syntax highlighting (probably using textChanged() signal), but that's pretty much as far as the requirements go.
Google searches for "QTextEdit vs QPlainTextEdit" and "QTextEdit compared to QPlainTextEdit" didn't give me any decent results that would compare the two classes.
From Qt's documentation:
QPlainTextEdit is an advanced viewer/editor supporting plain text. It
is optimized to handle large documents and to respond quickly to user
input.
QPlainText uses very much the same technology and concepts as
QTextEdit, but is optimized for plain text handling.
QPlainTextEdit works on paragraphs and characters. A paragraph is a
formatted string which is word-wrapped to fit into the width of the
widget. By default when reading plain text, one newline signifies a
paragraph. A document consists of zero or more paragraphs. Paragraphs
are separated by hard line breaks. Each character within a paragraph
has its own attributes, for example, font and color.
And later on:
Differences to QTextEdit
QPlainTextEdit is a thin class, implemented by using most of the
technology that is behind QTextEdit and QTextDocument. Its performance
benefits over QTextEdit stem mostly from using a different and
simplified text layout called QPlainTextDocumentLayout on the text
document (see QTextDocument::setDocumentLayout()). The plain text
document layout does not support tables nor embedded frames, and
replaces a pixel-exact height calculation with a line-by-line
respectively paragraph-by-paragraph scrolling approach. This makes it
possible to handle significantly larger documents, and still resize
the editor with line wrap enabled in real time. It also makes for a
fast log viewer (see setMaximumBlockCount()).
So the difference is that QPlainTextEdit is optimized for handling plain text, and can be used even with very large plain text files. Also the way text is formatted is simpler.
If you plan to support only plain texts, then QPlainTextEdit is the right choice.

help with type of window dialog resource needed

I am writing a windows program (no mfc) and need to output a status line to the operator every few seconds or so. I tried using rich text boxes but after so many hours it seems to hang up. Does anybody have an suggestions on what I can use instead?
People mentioned that my buffers might have been exhausted. I thought I had planned for that. After I had about 1000 lines displayed I would take the first 500 and remove them using the select and cut options in rich text boxes. I still ran into the same problem.
This question appears relevant, and this one too. But they don't give any concrete recommendations for an alternative to rich text boxes.
You might try the Scintilla control (scintilla.org) which does not appear to have any hard limitations on text size. It has a permissive license. It is used by many text editors such as Notepad++, Notepad2, Code::Blocks, FlashDevelop. I haven't tried it personally but there from the documentation it looks easy to use it in a Windows API application. Of course, it might be overkill for your purposes.
If you keep appending to the text in the control every few seconds for hours then you are probably running into some memory constraint on the control or the process. I think you would have this problem with any control you choose given update frequence and how long you're running the program.
Have you considered implementing a simple circular buffer for the content of the text box? Say only keep the last hour's messages. You could maintain a separate log file for history if the operator needed to go back in time for hours.
I ended up writing my own control to do this, essentially duplicating the Output window in Visual Studio. It was a success, but it ended up being much more code than I thought it would be when I started - I insisted on features such as auto-scrolling when the cursor was on the last line, select/copy, bold text, etc. It was backed by a std::deque so I could limit the number of lines stored for the window.
Unfortunately the code belongs to a former employer so I can't share it here.

How to implement QTextDocument serialization

This question I have asked before and just got answer that there is an open bug for this. But this is a really required feature and, I guess, each Qt programmer who programmes a more or less serious application, it is quite probable that there is used a QTextEdit and the data is inserted in QTextEdit is serialized and deserialized. Thus I consider this issue very importand and it can be useful for many Qt developers. So I have decided to discuss with good programmers how to implement operator<<(QDataStream, QTextDocument). Otherwise we should wait when Qt guys will be kind to do that by themselves :).
So say in a QTextEdit I have some pictures and text. In different fragments the text has different format. How to get the content of this kind of QTextEdit and how to serialize, in order to show then as it was?
EDIT: I know that I can get the formated text and images by using documnet() method, which returns QTextDocument. I also know that QTextDocument has no operator<<(QDataStream, QTextDocument) and there is a request for writting this operator but it is still open. So please help me to write this method.
I guess I should inherit the QTextDocument class, then to add a new member (a container) that stores all the names of resources that are present in the QTextEdit. Then I should serialize all resources by iterating on them by using the container I have defined. Is it a good solution? If yes, then could you please help me to implement? If no then please provide me with a better idea.
You already asked this question in April:
Qt - serialize/deserialaize text and picture
The answers are still the same.
Wait for Qt to fix QTBUG-9258
Perform the serialization yourself
Depending on your needs a quick and dirty way to do it would be to get the HTML representation of the contents with QTextEdit::toHtml, then base64 encode it. I'm not sure how this will work with pictures.
Please don't repost the same questions.
See here:
How to serialize and deserialize rich text in QTextEdit?