With QTextObjectInterface I get the frame around the text object:
QSizeF framedTextAttr::intrinsicSize(QTextDocument *doc, int posInDocument, const QTextFormat &format)
{
Q_ASSERT(format.type() == format.CharFormat);
const QTextCharFormat &tf = *(const QTextCharFormat*)(&format);
QString s = format.property(prop()).toString();
QFont fn = tf.font();
QFontMetrics fm(fn);
return fm.boundingRect(s).size();
}
void framedTextAttr::drawObject(QPainter *painter, const QRectF &rect, QTextDocument *doc, int posInDocument, const QTextFormat &format)
{
Q_ASSERT(format.type() == format.CharFormat);
QString s = format.property(prop()).toString();
painter->drawText(rect, s);
painter->drawRoundedRect(rect, 2, 2);
}
But the text becomes a single object, no more editable
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
setCentralWidget(new QTextEdit);
framedTextAttr *fa = new framedTextAttr;
editor()->document()->documentLayout()->registerHandler(framedTextAttr::type(), fa);
editor()->setPlainText("hic sunt\n leones !");
QTextCharFormat f;
f.setObjectType(fa->type());
QTextCursor c = editor()->document()->find("leones");
f.setProperty(fa->prop(), c.selectedText());
c.insertText(QString(QChar::ObjectReplacementCharacter), f);
}
And the result (here a picture):

It seems it's difficult to generalize. I'm not satisfied...
edit
Actually, it's feasible.
I've worked out some of the problems with the illustrated approach, and it seems to be viable also for folding/unfolding text in reusable fashion.

I've put my test project on GitHub.