@jsulm, I apologize, I should've mentioned it in the original post: one of the requirements of the project is that we can not use any 3rd party library for the text editor, except for Qt.
From what I see in the QScintilla github, it is ported to Qt on top of the TextEdit widget, so I will look further into their implementation to figure out how they've done it.
Apparently it is virtually impossible to do what I want because the QTextBlock itself hardcodes a QTextLayout in its ::layout() method (see here). Moreover, it seems that every hook we could use is only available in the private classes...
Now, the problem is that it prevents everybody wanting to implement custom behavior to create anything based on the QTextDocument and its associates. I wonder how the people who created text editors got away with this (probably implemented everything from scratch).
Well, at the end, the only thing I found that could work was to manually insert unicode U+002028 (Line Separator) wherever I want using QTextCursor, which is terrible because everytime the editor area width changes I have to remove the old ones and insert new ones...
As I'm not happy with the solution I found, I'll not mark this question as solved.
I played around with scrollbar calculation a long time ago and I remember that it was a bit confusing.
But AFAIR you have to set the QScrollBar::setValue() relative to QScrollBar::maximum() with the same ratio as QAbstractScrollArea::widget()::height() / calculatedPos.
(not sure - just guessing...)
What OS and Qt version are you using?
On windows the end-of-line (EOL) marking is done by \r\n, although I'm not sure how it is done in the QPlainTextEdit class, but it may worth to give a try.
IIRC QRegExp should be replaced QRegularExpression in recent code, but I don't think this is the problem.
And I'm not sure about the regex you posted: the caret should negate the content of the class, therefore matching any character not being a number or a spacing, resulting in exactly the opposite.
If you basically basically want to reject any string containing a letter, then you could try to reverse your regex to "[^a-z,A-z]+".
One thing in you code is that in your receive function your are looping over each byte you received and ask to update the widget. What is generally done when handling large amount of data in such small amount is that the processing is done in a different thread. Also the UI update should be batched, there's no real benefit to update your QPlainTextEdit content for every single byte you get.