Search code examples
qtsignalsqgraphicsitem

QTextDocument::contentsChanged doesn't seem to be triggered on formatting changes


I would like to do certain updates when the text contents change or font or alignment change on QGraphicsTextItem.

So I connected QTextDocument::contentsChanged() to a slot that does the update.

This signal is emitted whenever the document's content changes; for example, when text is inserted or deleted, or when formatting is applied.

The signal gets hit when I change the text - but setting text formatting or alignment doesn't seem to affect it.

.h
class MyTextItem : public QGraphicsTextItem
{
Q_OBJECT
public:
    MyTextItem();
    ~MyTextItem() {}
    void setItemFont(QFont f);
    void setItemAlign(Qt::Alignment a);
private slots:
    void updateItemOnContentsChanged();
private:
    void updateTextOnPropertyChanges();
};

.cpp
MyTextItem::MyTextItem()
{
    setTextInteractionFlags(Qt::TextEditorInteraction);
    connect(document(), SIGNAL(contentsChanged()), this, SLOT(updateItemOnContentsChanged()));
}
void MyTextItem::setItemFont(QFont f)
{
    setFont(f);
}
void MyTextItem::setItemAlign(Qt::Alignment a)
{
    QTextDocument *_document = document();
    QTextOption _option = _document->defaultTextOption();
    _option.setAlignment(a);
    _document->setDefaultTextOption(_option);
    setDocument(_document);
}
void MyTextItem::updateItemOnContentsChanged()
{
    updateTextOnPropertyChanges();
}
void MyTextItem::updateTextOnPropertyChanges()
{
    qDebug("changing something");
}

main.cpp
int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    QGraphicsScene s;
    QGraphicsView view(&s);
    s.setSceneRect(-50, -50, 500, 500);
    view.show();
    MyTextItem* t = new MyTextItem();
    t->setPlainText("Hello World !");   // Note this triggers update
    s.addItem(t);
    qDebug("1");
    qDebug() << t->font().family();
    t->setItemFont(QFont("Arial"));  // or t->setFont(QFont("Arial"));
    qDebug() << t->font().family();
    qDebug("2");
    t->setItemAlign(Qt::AlignRight);
    qDebug("3");
    return app.exec();
}

My debug output:

changing something
1
"MS Shell Dlg 2" // so the font is changing - yet no signal
"Arial"
2
3

(and if I type in the item on the scene I get changing something as well)
But no changing something after the setItemFont() or setItemAlign().

So changing text affects it - but changing font or alignment doesn't...

Do I understand wrong the part I set bold in the signal description ?
Why do I not see changing something after changing font or alignment...

I also wonder - does my changing the document() when I set alignment or wrap or other document properties affect the connect ? (it doesn't seem to...)

(Note I wrote the setItem* functions to be able to call the updateTextOnPropertyChanges() function - so I can make things work the way I need - but would be great if I didn't need them and just use the Qt ones, if the signal worked as I thought it would)


Solution

  • It seems that what falls under formatting is loosely defined.

    As you said, setItemFont() or setItemAlign() do not trigger the signal, but calling _document->setDocumentMargin(4.3); within your void MyTextItem::setItemAlign(Qt::Alignment a) method does.

    Also, contentsChanged() is a signal emitted by the QTextDocument class, so I'm not sure if calling methods on the QGraphicsTextItem object that change its appearance classifies as modifying the formatting of the QTextDocument.