PDA

View Full Version : rich text in tree widget



magland
26th October 2007, 17:50
What's the easiest way to display rich text in QTreeWidget or QTreeView items? If it involves implementing QTreeView::drawRow(), I'd be grateful for some help getting started ... is there an example I can copy?

Thanks!

jpn
26th October 2007, 17:57
Try something like what's in this post (http://www.qtcentre.org/forum/p-qstandarditem-subpart-of-the-text-as-bold-post28758/postcount4.html).

magland
26th October 2007, 18:33
Thanks, do you recommend I inherit QItemDelegate, or QAbstractItemDelegate?

wysota
26th October 2007, 19:26
Depends. If you don't want to display icons or anything (like selections), use QAbstractItemDelegate. Otherwise use QItemDelegate, just make sure you reimplement sizeHint() as well.

magland
26th October 2007, 20:38
Depends. If you don't want to display icons or anything (like selections), use QAbstractItemDelegate. Otherwise use QItemDelegate, just make sure you reimplement sizeHint() as well.

I want to use all features of QItemDelegate, except of course rendering text. So I inherited from that and overloaded as below. That works quite well. But my only problem now is that painter->translate(...) does not seem to be correct... it's off by about one line... any ideas?



void drawDisplay(QPainter *painter, const QStyleOptionViewItem &option,const QRect &rect, const QString &text) const {
painter->save();
QTextEdit edit;
QTextDocument *doc=edit.document();
if (highlighter) highlighter->setDocument(doc);
edit.setLineWrapMode(QTextEdit::NoWrap);

doc->setPlainText(text);
QAbstractTextDocumentLayout::PaintContext context;
doc->setPageSize( rect.size());
painter->translate(rect.x(),rect.y());
doc->documentLayout()->draw(painter, context);
painter->restore();
}

wysota
26th October 2007, 23:48
Remember that the size of the rectangle is off by one because of "historical reasons". You might be hitting the offset here. Try reducing the width and height of rect by one.

jpn
28th October 2007, 10:11
Also, to me it doesn't look like a very good idea to create a QTextEdit widget during every drawDisplay(). Wouldn't a QTextDocument suffice?

magland
29th October 2007, 01:44
Also, to me it doesn't look like a very good idea to create a QTextEdit widget during every drawDisplay(). Wouldn't a QTextDocument suffice?

I agree, but I couldn't figure out how to do QTextEdit::setLineWrapMode(QTextEdit::NoLineWrap) with QTextDocument. Do you know how to do that?

Also, I guess I should allocate a single QTextEdit and QTextDocument for the entire tree widget... and just keep calling setPlainText from within drawDisplay. Would that make more sense?

jpn
29th October 2007, 07:51
I agree, but I couldn't figure out how to do QTextEdit::setLineWrapMode(QTextEdit::NoLineWrap) with QTextDocument. Do you know how to do that?
No idea, but I'd take a look at QTextEdit sources and see how Trolls do it. I bet they do it with the help of QTextDocument or its document layout. ;)


Also, I guess I should allocate a single QTextEdit and QTextDocument for the entire tree widget... and just keep calling setPlainText from within drawDisplay. Would that make more sense?
Try profiling and see if there's any difference. Changing the document content causes a lot of re-layouting as well. I don't know which one is more light-weight; to create a new document from scratch or to re-layout new document content.

wysota
29th October 2007, 09:28
Trolls do everything with QTextControl, so I'm guessing the functionality is performed by this exact component. If I'm wrong, then it's probably in the competence of the text layout object - try there.

The Storm
10th March 2009, 10:44
Hi,

I followed this thread instructions and I created delegate to paint rich text and also to not draw the forus of items. I inherit QItemDelegate. Here's my code:



void ItemDelegate::drawDisplay( QPainter* painter, const QStyleOptionViewItem& option, const QRect& rect, const QString& text ) const
{
QPen pen = painter->pen();
QPalette::ColorGroup cg = option.state & QStyle::State_Enabled ? QPalette::Normal : QPalette::Disabled;

if( cg == QPalette::Normal && !(option.state & QStyle::State_Active) )
cg = QPalette::Inactive;

if( option.state & QStyle::State_Selected )
{
painter->fillRect( rect, option.palette.brush(cg, QPalette::Highlight) );
painter->setPen( option.palette.color(cg, QPalette::HighlightedText) );
}
else
{
painter->setPen( option.palette.color(cg, QPalette::Text) );
}

if( text.isEmpty() )
return;

painter->save();
QTextDocument doc;
doc.setHtml( text );
doc.adjustSize();
QAbstractTextDocumentLayout::PaintContext context;

doc.setPageSize( rect.size() );

painter->setClipRect( rect );
painter->translate( rect.x(), rect.y() );
doc.documentLayout()->draw( painter, context );
painter->restore();
}

void ItemDelegate::drawFocus( QPainter* painter, const QStyleOptionViewItem& option, const QRect& rect ) const
{
}


The code is working fine but I am no longer able to use style sheets on the items. In order to use style sheets I think that I have to inherit QStyledItemDelegate. But QStyledItemDelegate doesn't have virtual functions drawDisplay() and drawFocus(). So how I will be able now to remove the focus dotted lines of items and to draw the rich text and I really want to avoid to rewrite the whole paint() function... Please help. :)

wysota
10th March 2009, 15:56
If you want to use QStyledItemDelegate, you have to reimplement those methods that it delivers, unfortunately. Focus is kept inside the style option object, you can copy it and make sure the focus flag is off before calling the base class implementation.

The Storm
11th March 2009, 10:47
Thank you a lot. For me (a person who is not in good standing with math) it was a bit hard to find the correct rect on where I should place the text, sinse I put a Icon on the item too. The good in QItemDelegate was that it gived me as argument the exact rect where a text can be placed. In QStyledItemDelegate I wasn't able to find a correct way to calculate this so now I use hardcoded rect. If you have an idea how I can calculate the correct rect for the text, please tell me. :)

wysota
11th March 2009, 11:09
You have the sources of Qt, take a look at the appropriate method.

The Storm
11th March 2009, 13:20
I lost half a day trying to figure it out via the Qt sources. The bad part is that there is thoose private pointer d that make the things hard for me. When I have more time I will try to cut out the peaces of code that combined can give me correct result.

The Storm
11th March 2009, 15:54
Ok just one more question. :) The selected item is highlighted as it should be but the icon that I have set to it receives a blue highlight too. What variable I have to modify in to the option pointer in order to make the icon/picture to remain in normal state?

I tried with
option->showDecorationSelected = false;
before the paint and the whole highlightion dissappeared except that on the picture. This makes me think that there should be some kind of variable to just leave the picture in normal state but I can't find it...

wysota
11th March 2009, 16:53
You should paint the icon again after everything else is drawn. That's the only solution I can think of.

The Storm
11th March 2009, 20:42
I was afraid that you will say that. :) Not good solution but sinse it seems to be the only way I will do it.

aamer4yu
12th March 2009, 09:47
You can try modifying QStyleOption::state before calling the drawDecoration function.


QStyle::State state = option.state;
state = state & (!QStyle::State_Selected);

something like that...

The Storm
12th March 2009, 14:07
Yep I tried removing the QStyle::State_Selected flag but this removes the whole highlight not only on the picture, i.e. the user don't know witch is the active item. :)