1

I have rich text items implemented using QGraphicsTextItem

To set font size, for example:

void set (int fontSize) { 
    QTextCursor _cursor = textCursor();
    QTextCharFormat _format;
    _format.setFontPointSize(fontSize);
    _cursor.mergeCharFormat(_format);
    setTextCursor(_cursor); }

A lot more complicated is to read the font size.
Assuming I have a selection, I must iterate through the document, through all QTextBlock, QTextFragment, reading the QTextCharFormat ...
But the simple option, if there is no selection, just reading the font size at cursor:

int get () {
    return textCursor().charFormat().fontPointSize(); }

This works, but I found 3 issues:

1) Setting font size by QGraphicsTextItem properties:

QFont f = font();
f.setPointSize(20);
setFont(f);

this returns 0 by my get function above. To set the font size for the entire item, I have to use the same method as in the set function.
Shouldn't the setFont method set a font that can be read from the QTextCursor ?

2) setHtml can set formatting - but I don't see any way to read that formatting
How can I read the rich text formatting from an html fragment ? Is the only posiblity, parsing the html ?

3) (my current stumbling block)
Copy formatted text from an outside source and paste in the QGraphicsTextItem seems to maintain the formatting of the source - but how can I read that formatting ?
The get method above reads font size 0 if the text was pasted from outside.
font().pointSize() always returns 8. (I have not set it so I imagine that is a default)
Is there another method to read the text format ?
is the clipboard text formatted using html ?

How can I find the font size (or any other formatting) from the pasted text ?

(The same questions apply to block formatting, like alignment).

Thalia
  • 13,637
  • 22
  • 96
  • 190

1 Answers1

1

I think most of your problems could be solved by getting the QTextDocument for your QGraphicsTextItem object and work with it. QTextDocument and its methods (like QTextFormat::property(int propertyId)) can help you to get a lot of properties for your text.

1) If you set the size using the QFont object, you should get the size using the same way.

2) When you set the text using html, QGraphicsTextItem::font() is not useful so you need to get the QTextDocument and use their functions instead.

3) Same as 2. I think... because I don't have your code to test it :)

Well, here you have a code as an example. I hope this answer helps you.

#include <QApplication>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QGraphicsTextItem>
#include <QTextCursor>
#include <QTextCharFormat>
#include <QFont>
#include <QDebug>
#include <QTextDocument>
#include <QTextBlock>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    QGraphicsScene scene;
    QGraphicsView view(&scene);

    /* ITEM 1 */
    QGraphicsTextItem* item_1  = new QGraphicsTextItem("QGraphicsTextItem 1");
    item_1->setTextInteractionFlags(Qt::TextEditorInteraction);
    QFont f = item_1->font();
    f.setPointSize(30);
    item_1->setFont(f);

    qDebug() << "textCursor().position() (returns 0): " <<
                item_1->textCursor().position();
    qDebug() << "textCursor().charFormat().fontPointSize() (returns 0): " <<
                item_1->textCursor().charFormat().fontPointSize();
    qDebug() << "font().pointSize() (returns 30 - OK!): " <<
                item_1->font().pointSize();

    QTextDocument* doc = item_1->document();
    f = doc->defaultFont();
    qDebug() << "pointSize (returns 30 - OK!): " << f.pointSize();

    scene.addItem(item_1);

    /* ITEM 2 */
    QGraphicsTextItem* item_2  = new QGraphicsTextItem();
    item_2->setPos(0, 50);
    item_2->setHtml("<html><head/><body><p>"
                    "<span style=\"font-size:14pt; font-weight:600;\">QGraphics</span>"
                    "<span style=\"font-size:24pt; font-weight:600;\">TextItem 2</span>"
                    "</p></body></html>");

    qDebug() << "font().pointSize() (returns 8, the default value): "
             << item_2->font().pointSize();

    doc = item_2->document();
    f = doc->defaultFont();
    qDebug() << "pointSize (returns 8, the default value): " << f.pointSize();

    QVector<QTextFormat> formats = doc->allFormats();
    QVectorIterator<QTextFormat> i(formats);
    while (i.hasNext()) {
        QTextFormat format = i.next();
        if (format.property(QTextFormat::FontPointSize).isValid())
            qDebug() << "format.property (returns 14 or 24): " <<
                        format.property(QTextFormat::FontPointSize).toInt();
    }

    /*
     * Get the block of text. In this example, we only have one block, but
     * two text fragments (see below)
     */
    QTextBlock text_block = item_2->document()->findBlock(1);
    QTextBlock::iterator it;

    for (it = text_block.begin(); !(it.atEnd()); ++it) {
        QTextFragment currentFragment = it.fragment();
        if (currentFragment.isValid())
            qDebug() << "currentFragment.text(): " << currentFragment.text();
            qDebug() << "currentFragment.charFormat().font().pointSize() "
                        "(returns 14 or 24, depending on"
                        "the current text fragment): " <<
                        currentFragment.charFormat().font().pointSize();
    }

    scene.addItem(item_2);

    view.setFixedSize(640, 480);
    view.show();
    return a.exec();
}
Tarod
  • 6,732
  • 5
  • 44
  • 50
  • Thanks for the example, so basically it is impossible to implement rich text with user interaction - using cursor position, selection and so on - with any html or any clipboard input, that is what I understand. Since that is what I have to do: implement rich text editing, the only way then is to disable any html formatting and only allow plain text paste. Is that true ? Or do I understand your answer wrong ? – Thalia Sep 29 '15 at 13:17
  • My code... is gigantic... but I inserted the relevant functions, to set the font size (at cursor point so new text will have that font size) or for a selected text fragment - and also to get the font at cursor position. – Thalia Sep 29 '15 at 13:20
  • Your code answers my question (2) - and also confirms my statement from (1) - except, there seems to be only a way to get all formats in the entire document. There is no way to get it at a specific point (e.g. position) or for a specific range (selection - from position a to position b). – Thalia Sep 29 '15 at 13:25
  • I still find it confusing, that for 3 different methods of setting text formatting (setting font globally, html formatting, and `QTextCursor`+`QTextCharFormat` for rich text), there are 3 different methods of reading it, each incompatible with any of the others, each completely unable to read anything that any other method has set - and there may be more methods that I have not discovered. – Thalia Sep 29 '15 at 13:32
  • Again, the key is to use the class `QTextDocument` + `QTextCursor`. If you have a `QTextCursor`, you could iterate over its `QTextBlock` and get the information for each `QTextFragment`. If you need the fragment for the selected text, you can use `QTextCursor::selection()`. In my opinion, use or not HTML makes no difference to me when the aim is to retrieve information about characters in the text. I've updated my answer. Now we have a rich text with two text blocks and also some lines of code to iterate over those text blocks. BTW, interesting questions! :) – Tarod Sep 30 '15 at 07:58