QTextEdit change font of individual paragraph/block
Asked Answered
M

3

6

Using a QTextEdit, I need to change the font attributes of each paragraph individually. This is similar to how many word processors change the font of a paragraph when the user select a style from a menu (not a specific formatting).

Ideally, I would like to apply a QTextCharFormat (or equivalent) to a block (paragraph) just before it is laid out and rendered, but I would prefer that no font attribute be actually inserted in the text, as I don't want this information in the file but I need to preserve any bold/italic/underline attributes that the user might have set to words within paragraphs (I intend to save the needed information in a QTextBlock::userData). However, I can't figure where I would need to insert a function to perform this task.

I figured I could not change the QTextCharFormat of a paragraph from either QTextBlock nor QTextCursor as this only applies to new blocks, it doesn't affect blocks with existing text.

I checked out QTextLayout but I don't think my answer is there.

I have been looking for a solution to this problem for a few days now. I would be really gracious for any pointer in the right direction.

I have years of experience with C++, but I'm somewhat new to Qt. Using Qt 4.8.

Edit:

I added emphasize (bold) above to an important part of what I'm trying to do. In other word, what I'd really like to do is be able to apply the font attributes to the block of text (perhaps a temporary copy) just before it is displayed. I'm totally comfortable with deriving and modifying (even reimplement) any class that I need to in order to achieve that goal, but I need to be pointed to the right direction as to what I actually need to change. As a last resort, I could also modify some Qt class directly if that is necessary for the task, but again would need to know what class I need to touch. I hope this is clearer. I find it difficult to explain this without being allowed to tell you what the application will do exactly.

Mage answered 31/12, 2014 at 5:35 Comment(0)
K
10

[Required Libraries]

#include <QTextEdit>    // not needed if using the designer

#include <QTextDocument>
#include <QTextBlock>
#include <QTextCursor>

[Strategy]

QTextDocument

I need it to manage the blocks. The function QTextDocument::findBlockByNumber is quite handy to locate the previous blocks, and I think it is what you are after.

QTextBlock

Container for block texts. A nice and handy class.

QTextCursor

Surprisingly, there is no format-setter in QTextBlock class. Therefore I use QTextCursor as a workaround since there are four format-setters in this class.

[Code for formatting]

// For block management
QTextDocument *doc = new QTextDocument(this);
ui->textEdit->setDocument(doc);  // from QTextEdit created by the Designer
//-------------------------------------------------
// Locate the 1st block
QTextBlock block = doc->findBlockByNumber(0);

// Initiate a copy of cursor on the block
// Notice: it won't change any cursor behavior of the text editor, since it 
//         just another copy of cursor, and it's "invisible" from the editor.
QTextCursor cursor(block);

// Set background color
QTextBlockFormat blockFormat = cursor.blockFormat();
blockFormat.setBackground(QColor(Qt::yellow));
cursor.setBlockFormat(blockFormat);

// Set font
for (QTextBlock::iterator it = cursor.block().begin(); !(it.atEnd()); ++it)
{
    QTextCharFormat charFormat = it.fragment().charFormat();
    charFormat.setFont(QFont("Times", 15, QFont::Bold));

    QTextCursor tempCursor = cursor;
    tempCursor.setPosition(it.fragment().position());
    tempCursor.setPosition(it.fragment().position() + it.fragment().length(), QTextCursor::KeepAnchor);
    tempCursor.setCharFormat(charFormat);
}

Reference: How to change current line format in QTextEdit without selection?


[DEMO]

Building Environment: Qt 4.8 + MSVC2010 compiler + Windows 7 32 bit

The demo is just for showing the concept of setting the format on a specific block.

Plain text input

enter image description here

Format 1 (notice that it won't bother the current cursor in view)

enter image description here

Format 2

enter image description here

Korella answered 31/12, 2014 at 10:26 Comment(2)
Great job! +1 for you!Lilienthal
You clearly put a lot of effort in that answer, and I will accept it if I can't find more precisely what I'm trying to do. What I'm looking for is a way for changing the appearance of a paragraph without actually inserting any formatting information within the said paragraph. (I will improve my question to emphasize this point.)Mage
A
0

You can use QTextCursor to modify existing blocks.

Just get a cursor and move it to the beginning of the block. Then move it with anchor to create a selection.

Set this cursor to be the current cursor for the text edit and apply your changes.

Alatea answered 31/12, 2014 at 8:5 Comment(0)
P
-1

QTextEdit accepts HTML so all you have to do is to format your paragraphs as HTML. See example below:

QString text = "<p><b>Paragraph 1</b></p><p><i>Paragraph 2</i></p>";
QTextCursor cursor = ui->textEdit->textCursor();
cursor.insertHtml(text);

That will create something like this:

Paragraph 1

Paragraph 2

Having said that, there is only a subset of HTML that is supported in Qt. See Supported HTML Subset

Prehensible answered 31/12, 2014 at 8:8 Comment(9)
Undoubtedly, HTML is a good way for formatting, but I am afraid it's not what OP wants because he explicitly mentioned "I would prefer that no font attribute be actually inserted in the text, as I don't want this information in the file but I need to preserve any bold/italic/underline attributes that the user might have set to words within paragraphs"Korella
Thanks @Korella for reading my entire post. This part that you quoted is actually the part that causes me problems. I will improve my question to emphasize on that. As for this answer, I'm really writing an editor. I think your proposed solution is more for a widget that would merely display data.Mage
@user23430 Hmm...so you want to set the font attribute before the user enters the content? Besides, it seems the number of text blocks need to be definite.Korella
@Korella No, no. The use enter his content as usual. But may decide to set a different style on a new paragraph before typing the content, or may decide to change the style later when the text has been typed. The feature I need is really like the style feature of major word processors, but differs in that I'd like the actual formatting information not to be included in the data. The person who will receive the finished file only cares to know what style a paragraph is (title, chapter name, regular body text, etc) he doesn't want to see what font the user liked to represent that style.Mage
@user23430 Although my approache seems to be only for changing the existing block style, the concept is basically the same for changing the style of a new pragraph: it doesn't matte there's a text or not, you can set the style on it if the block exist. You add a new block, set style on it (not typing yet), then enter the content.Korella
But your approach will actually insert the formatting information within the text, isn't it? I wouldn't mind if there was a easy way to strip out the formatting when saving the file. But I can't distinguish between bold that was put automatically from the style and bold that the user specifically set by selecting the text and hitting Bold on the toolbar. When the file is sent to the final person, the later must be preserved, but the former shouldn't be there. I'm starting to believe my concept was more complicated that it initially sounded in my head.Mage
@TomDuhamel Simply put, it sounds like a MVC problem for a text editor. Previously I thought formatting information within the text is something about HTML. Now I think what you want is like a separate view which can display certain font style on specific blocks and doesn't bother the current model (text file).Korella
@Korella I think you just got it :) Consider this: <paragraph><style>Title</style><text>This is a <i>nice</i> title</text></paragraph>Mage
@Korella This is how the data might be represented in XML when saved to a file. "style" is only preserved as abstract, and is represented on the user's screen what whatever he wants a title to look like, but another user may want a different representation when viewing the same file, and the final receiver doesn't want any representation at all because he will actually format the document based on the "style" of each each paragraph (likely done automatically, so he doesn't have to see the text and doesn't have to determine by hand what each paragraph represent).Mage

© 2022 - 2024 — McMap. All rights reserved.