PDA

View Full Version : [Qt4] Noob and custom Item Delegate



naresh
13th March 2006, 10:51
Hello! I'm trying to create custom item delegate to view multiline text in QTreeView properly... So I've started trying to create my delegate... the result is that it doesn't draw anything (the scrollbar appear when i resize app window so items are there) :| Here is some code:

painting:


void rosterDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
painter->setRenderHint(QPainter::TextAntialiasing);
painter->setPen(Qt::NoPen);

if (option.state & QStyle::State_Selected)
painter->setBrush(option.palette.highlight());
else
painter->setBrush(QBrush(Qt::white));

QTextOption textOption;
textOption.setWrapMode(QTextOption::WordWrap);

QSize sizehint=sizeHint(option, index);
int width=Qxygen->viewWidth();
int height=ceil((sizehint.width()*sizehint.height())/width);

rosterItem *item = static_cast<rosterItem*>(index.internalPointer());

painter->drawText(QRectF(option.rect.x(), option.rect.y(), width, height), /* FROM WHERE GET THAT TEXT? */, textOption);
}


here is my modelView data


QVariant rosterView::data(const QModelIndex &index, int role) const
{
if (!index.isValid())
return QVariant();

if (role == Qt::DisplayRole)
{
rosterItem *item = static_cast<rosterItem*>(index.internalPointer());

if(descr && !(item->isGroup())) // CHECKS IF VIEW HAS TO SHOW ITEM DESCRIPTION AND ITEM ISN'T GROUP - GROUPS DOESN'T NEED DESCRIPTION
{
if((item->data(1)).isEmpty()) return item->data(index.column());
else return QString(item->data(index.column()))+"\n"+QString(item->data(1));
}
else
{
return item->data(index.column());
}
}
else if(role == Qt::DecorationRole)
{
rosterItem *item = static_cast<rosterItem*>(index.internalPointer());
if(item->isGroup())
{
if(item->isExpanded())
{
return QIcon(":expanded.png");
}
else
{
return QIcon(":collapsed.png");
}
}
else
{
return QIcon(":dnd.png");
}
}
else
{
return QVariant();
}
}


Now i have no idea how to make my delegate paint icon and text (in one column). Any suggestion/help?

wysota
13th March 2006, 12:44
It's best to see how the default delegate does it. Where to get the text to render? From the model :) Using data(index, Qt :: DisplayRole). But in your case it should be enough to change style options (to turn on word wrapping) and call the default delegate.

naresh
13th March 2006, 12:59
Turn on word wrapping to what? QTreeView and QItemDelegate has no such property. I also need to display description italic... I know that QTreeView has property uniformRowHeights and its already changed to false (by calling setUniformRowHeights(FALSE)). So where to set word wrapping and is it possible to display description in italics?

wysota
13th March 2006, 14:01
You might want to take a look at QStyleOptionViewItem (http://doc.trolltech.com/4.1/qstyleoptionviewitem.html) class. You have the ability to change font settings there.

Looks like I might have been wrong with the word wrapping thing, you need to set it directly.

Anyway, this is my multiline drawing "thing" (it's not a delegate but rather part of the view, but all rules remain the same).


void ColumnChartView::drawRowNames( QPainter * p ) {
int itemwidth = itemWidth();
int seriesCount = model()->columnCount();
int columnWidth = itemWidth()/seriesCount;
int maxh = chartSize().height();
int valueSpan = _maxVal - _minVal;
uint rowHeight = (_flags & XTitle) ? _canvasVMargin-QFontMetrics(font()).height()-2 : _canvasVMargin;
p->save();
for(int i=0;i<model()->rowCount(rootIndex());i++) {
QRect rect(qRound(_canvasHMargin+itemwidth/4+i*itemwidth*3/2), maxh+_canvasVMargin, itemwidth, rowHeight);
QStyleOptionViewItem opt = getOptionsForRowLabel(i);
p->setFont(opt.font);
p->setPen(opt.palette.color(QPalette::Normal, QPalette::Text));
p->drawText(rect,opt.displayAlignment|Qt::TextWordWra p,QAbstractItemDelegate::elidedText(fontMetrics(), rect.width(),Qt::ElideRight,model()->headerData(i, Qt::Vertical).toString()));
}
p->restore();
}

In your case you need to use model()->data() instead of model()->headerData().

Just for completeness:


QStyleOptionViewItem ColumnChartView::getOptionsForRowLabel( int row ) {
QStyleOptionViewItem opt = viewOptions();
opt.displayAlignment |= Qt::AlignHCenter;
opt.displayAlignment &= ~Qt::AlignVCenter;
opt.displayAlignment |= Qt::AlignTop;
QVariant value;
value = model()->headerData(row, Qt::Vertical, Qt::FontRole);
if(value.isValid())
opt.font = qvariant_cast<QFont>(value);
value = model()->headerData(row, Qt::Vertical, Qt::TextColorRole);
if(value.isValid() && qvariant_cast<QColor>(value).isValid())
opt.palette.setColor(QPalette::Text, qvariant_cast<QColor>(value));
return opt;
}

naresh
13th March 2006, 14:56
And when should i call drawRowNames?

wysota
13th March 2006, 15:26
You shouldn't :) I told you, it is part of my own code which does something different. But it behaves the same as the painting routine from a delegate. The part you might find interesting is the way to call drawText() and a way to set and use wanted item options (this is the way to transfer data between the view and the delegate -- for data transfer between the model and the delegate model()->data() should be used).

What my code does is to render a multiline text (if it can be wrapped to fit into the desired rectangle) or elide it if it's not possible to fit it all.

You might also want to reimplement sizeHint() for the delegate and calculate the size needed to fit your item (using QFontMetrics).

naresh
13th March 2006, 16:08
Well I've updated my delegate paint routine and still result is blank... Here it is:


void rosterDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
painter->setRenderHint(QPainter::TextAntialiasing);
painter->setPen(Qt::NoPen);

if (option.state & QStyle::State_Selected)
painter->setBrush(option.palette.highlight());
else
painter->setBrush(QBrush(Qt::white));

QTextOption textOption;
textOption.setWrapMode(QTextOption::WordWrap);

rosterItem *item = static_cast<rosterItem*>(index.internalPointer());

int width=Qxygen->viewWidth(), height;

QFontMetrics fmetrics=Qxygen->fontMetrics();

if(item->data(1).isEmpty())
{
height=fmetrics.height();
}
else
{
height=fmetrics.height()+fmetrics.height()*ceil(fm etrics.width(item->data(1))/width);
}

QRect rect(option.rect.x(), option.rect.y(), width, height);

painter->drawText(rect,Qt::TextWordWrap,QAbstractItemDelega te::elidedText(static_cast<const QFontMetrics&>(Qxygen->roster()->fontMetrics()), rect.width(),Qt::ElideRight,Qxygen->model()->data(index, Qt::DisplayRole).toString()));

printf("Width: %d Height:%d\n", width, height);
}

Still no idea why it doesn't print anything. As i said before my QTreeView behaves like there were all items... The scroll bar shows when i resize whole app :confused:

wysota
13th March 2006, 17:04
painter->setPen(Qt::NoPen);

How do you expect to paint anything without a pen? :)

naresh
13th March 2006, 18:02
Ok i've made even painting of icon, but it doesn't paint with the height i requested :|

Here's code:

void rosterDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
painter->setRenderHint(QPainter::TextAntialiasing);
//painter->setPen(Qt::NoPen);

if (option.state == QStyle::State_Selected)
painter->setBrush(option.palette.highlight());
else
painter->setBrush(QBrush(Qt::white));

QTextOption textOption;
textOption.setWrapMode(QTextOption::WordWrap);

rosterItem *item = static_cast<rosterItem*>(index.internalPointer());

int width=Qxygen->viewWidth(), height;

QFontMetrics fmetrics=Qxygen->fontMetrics();

if(item->data(1).isEmpty())
{
height=fmetrics.height();
}
else
{
height=fmetrics.height()+fmetrics.height()*qRound( fmetrics.width(item->data(1))/width);
if(fmetrics.width(item->data(1))%width>0)
height+=14;
}

printf("Width: %d Height:%d\n", width, height);

QImage img=Qxygen->model()->data(index, Qt::DecorationRole).value<QImage>();

QRect irect(option.rect.x(), option.rect.y(), img.width(), img.height());
QRect rect(option.rect.x()+img.width()+2, option.rect.y(), width-img.width()-2, height);

QTextOption opt;
opt.setWrapMode(QTextOption::WordWrap);
opt.setAlignment(Qt::AlignTop|Qt::AlignLeft);

painter->drawImage(irect, img);
// painter->drawText(rect, Qxygen->model()->data(index, Qt::DisplayRole).toString(), opt);
painter->drawText(rect, Qt::TextWordWrap|Qt::AlignLeft|Qt::AlignTop, Qxygen->model()->data(index, Qt::DisplayRole).toString());
// painter->drawText(rect,Qt::TextWordWrap,elidedText(static_c ast<const QFontMetrics&>(Qxygen->roster()->fontMetrics()), rect.width(),Qt::ElideRight,Qxygen->model()->data(index, Qt::DisplayRole).toString()));
}

The painted text is in one line... When I resize app (height is calculated well i can see on console output) text isnt wrapped its only "hidden" behind border... Is there any possibility to put there rich text?

wysota
13th March 2006, 18:14
Ok i've made even painting of icon, but it doesn't paint with the height i requested :|

You can't "request" height. paint() only paints an item, it doesn't "set" its height. If you don't provide a boundingRect (or don't enable clipping) the text (or whatever you draw) will "flow out" of the item rectangle. Did you reimplement sizeHint for the delegate as I suggested (QItemDelegate)?

naresh
13th March 2006, 18:22
I didnt reimplement sizeHint... can you show me an example? I'm calculating width and height in paint (lines 20-29). Would you mind explaining me what were you mean by "don't enable clipping" and "boundingRect" ? ? ?

wysota
13th March 2006, 18:26
I didnt reimplement sizeHint... can you show me an example?
Take a look at QItemDelegate::sizeHint.


Would you mind explaining me what were you mean by "don't enable clipping"
QPainter::setClipping (see "Clipping").


and "boundingRect" ? ? ?
From QPainter::drawText:

The boundingRect (if not null) is set to the actual bounding rectangle of the output.

and QPainter::boundingRect.


BTW. sizeHint item role may come in handy too. Maybe it's enough to make an item larger, you might want to try it.

naresh
13th March 2006, 20:15
reimplementing sizeHint helped but not as i expected... It makes visible only 2 lines of text, (so it's viewing minimal size about 28px for items with description), then if i resize other words are cut... here is code:


void rosterDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
painter->setRenderHint(QPainter::TextAntialiasing);
if (option.state==QStyle::State_Selected)
painter->setBrush(Qxygen->roster()->palette().highlight());
else
painter->setBrush(QBrush(Qt::white));

QTextOption textOption;
textOption.setWrapMode(QTextOption::WordWrap);

rosterItem *item = static_cast<rosterItem*>(index.internalPointer());

int width=Qxygen->viewWidth(), height;

QFontMetrics fmetrics=Qxygen->fontMetrics();

QImage img=Qxygen->model()->data(index, Qt::DecorationRole).value<QImage>();

QRect irect(option.rect.x(), option.rect.y()+2, img.width(), img.height());
QRect nrect(option.rect.x()+img.width()+2, option.rect.y()+2, width-img.width()-2, fmetrics.height());

painter->drawImage(irect, img);

// CONTACT NAME
painter->drawText(nrect, Qt::AlignLeft|Qt::AlignTop, elidedText(static_cast<const QFontMetrics&>(Qxygen->roster()->fontMetrics()), nrect.width(),Qt::ElideRight,item->data(0)));

if(!item->data(1).isEmpty())
{
int height=fmetrics.height()*qRound(fmetrics.width(ite m->data(1))/width);
if(fmetrics.width(item->data(1))%width>0)
height+=fmetrics.height();

QRect drect(option.rect.x(), option.rect.y()+img.height()+2, width, height);
// DESCRIPTION
painter->drawText(drect, Qt::TextWordWrap|Qt::AlignLeft|Qt::AlignTop, item->data(1));
}
}

QSize rosterDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
rosterItem *item = static_cast<rosterItem*>(index.internalPointer());
int width=Qxygen->viewWidth(), height;

QFontMetrics fmetrics=Qxygen->fontMetrics();

QImage img(Qxygen->model()->data(index, Qt::DecorationRole).value<QImage>());

if(item->data(1).isEmpty())
{
height=img.height()+2;
}
else
{
height=img.height()+2+fmetrics.height()*qRound(fme trics.width(item->data(1))/width);
printf("%d %d\n", height, qRound(fmetrics.width(item->data(1))/width));
if(fmetrics.width(item->data(1))%width>0)
height+=fmetrics.height();
}

return QSize(width, height+2);
}

also highlighting selected item doesnt work :| But i don't care about that

Any idea why it draws only 2 lines? boundingRect didn't help and setClipping didn't help too... After setting clipping to TRUE nothing was painted :|

wysota
13th March 2006, 21:17
Highlighting doesn't work because you ignore the style options used for that. Are you inheriting QAbstractItemDelegate or QItemDelegate?

As for the size hint -- try setting some (big) constant value and see if that helps.


After setting clipping to TRUE nothing was painted
Did you set a rectangle to use for clipping? If not, then you probably "clipped out" the whole painter.

naresh
13th March 2006, 21:20
The reason for not painting all lines after resize is that painting isn't called after resize... I need to cath resize event, and write something like "repaintAll". And how to make highlight work? What do you mean "ignore the style options". Im inheriting QItemDelegate

naresh
13th March 2006, 23:10
In attachments there are screens showing how does it behave.

1. Everything is fine!
2. When resized empty line left
3. When collapase and expand group everything looks fine

wysota
13th March 2006, 23:29
Does the view ask the delegate for the sizeHint after resize? (use qDebug to check that out).

naresh
14th March 2006, 05:38
I have no idea how to check that :| (just call qDebug()?, where?)

I've added drawRect in paint and the result is like this (screens). It looks like the option.rect.x() and option.rect.y() doesn't change at all, only when collapse and expand group and it change only for items in collapsed group :|

wysota
14th March 2006, 11:32
I have no idea how to check that :| (just call qDebug()?, where?)


In your sizeHint implementation of the delegate subclass.

BTW. Did you try just using sizeHint role for your model?

naresh
14th March 2006, 12:57
Ok I've added before return in sizeHint something like this:


qDebug("w:%d h%d", width, height)

And in paint at end something like this:


Qxygen->model()->setData(index, sizeHint(option,index), Qt::SizeHintRole);

Everytime I'm resizing window the proper width and height is print on console for every item :|

wysota
14th March 2006, 14:39
And in paint at end something like this:


Qxygen->model()->setData(index, sizeHint(option,index), Qt::SizeHintRole);


What is this?????????????????????????????????????????????? ??
You can't manipulate the model from a delagate (or the view)! It ruins the whole concept of having a model and a view in the first place. Did you have a look at my example? You can manipulate item height by using size hint role without even touching the delegate. So the only thing you need to do with the delegate is to provide multi line text rendering (code for which btw. is presented in this thread too).

BTW. I wanted to ask that question much earlier -- what is that strange "Qxygen" member for? You can access the model through a model index, so what do you need it for?

I think you should... hmm... redesign your approach to the whole problem. You want contacts and descriptions of them and icons and all that divided into groups. For me you can do it in two ways:
1. description can be a child of a contact
2. description can be a property (role) of a contact

In the first case you have a parent-child relation, which can easily be handled by using a tree (which has additional benefits of being able to (1) show or hide the description when you need it, (2) add more "properties" for the contact if you need them (for example a photo, cell phone number or whatever you want) each of them separated from others (meaning you can "click" on each of the properties and act upon clicking on them) and (3) you don't have to subclass the delegate or the subclass can be very trivial.

In the second case, you can use roles to achieve more or less the same -- you define DescriptionRole (or use ToolTipRole for that), CellPhoneRole, PhotoRole and whatever other properties you want. Then you have to subclass the delegate. First thing I would do would be to look at implementation of QItemDelegate::sizeHint to see how it changes item sizes and maybe implement your own based on that. Then you need to implement tha painting routine, which should look more or less like so:
1. if I'm paining a group node (no valid parent), call QItemDelegate implementation
2. if I'm painting a contact node (has valid parent), call own custom routine

And in the custom routine:
1. Calculate size and position of each of the "properties"
2. Paint each property according to style options and active properties


Then you can manipulate everything just by changing the model -- you don't have to touch the view (that's the whole concept of MVC, right?). You can turn on and off every property you want by either adding or removing nodes (approach 1) or changing item roles (approach 2). First approach is superior to the second one, as it's simpler (you don't have to calculate to many things yourself) and more powerful (you can handle each property separately as each of them is represented by a different item).

naresh
14th March 2006, 15:31
Well i'm chosing the way with delegate becouse i will add some more features to paint... Your're right i dont need Qxygen (witch is just parent class, not view), but how can i recivie viewport width?

wysota
14th March 2006, 15:51
Through QStyleOptionViewItem which gets passed as a parameter to the delegates paint routine (it has a "rect" member which tells the delegate where to paint).

naresh
14th March 2006, 16:02
Here is "fixed" code for delegate


void rosterDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
painter->setRenderHint(QPainter::TextAntialiasing);
if (option.state==QStyle::State_Selected)
painter->setBrush(option.palette.highlight());
else
painter->setBrush(QBrush(Qt::white));

rosterItem *item = static_cast<rosterItem*>(index.internalPointer());

int width=sizeHint(option,index).width(), height;

QFontMetrics fmetrics=option.fontMetrics;

QImage img=static_cast<rosterItem*>(index.internalPointer())->image();

QRect irect(option.rect.x(), option.rect.y()+2, img.width(), img.height());
QRect nrect(option.rect.x()+img.width()+2, option.rect.y()+2, width-img.width()-2, fmetrics.height());

painter->drawImage(irect, img);

// CONTACT NAME
painter->drawText(nrect, Qt::AlignLeft|Qt::AlignTop, elidedText(fmetrics, nrect.width(),Qt::ElideRight,item->data(0)));

if(!item->data(1).isEmpty())
{
int height=fmetrics.height()*qRound(fmetrics.width(ite m->data(1))/width);
if(fmetrics.width(item->data(1))%width>0)
height+=fmetrics.height();

QRect drect(option.rect.x()+1, option.rect.y()+img.height()+2, width, height);
// DESCRIPTION
painter->drawText(drect, Qt::TextWordWrap|Qt::AlignLeft|Qt::AlignTop, item->data(1));
}
}

QSize rosterDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
rosterItem *item = static_cast<rosterItem*>(index.internalPointer());
int width=option.rect.width(), height;

QFontMetrics fmetrics=option.fontMetrics;

QImage img=static_cast<rosterItem*>(index.internalPointer())->image();

if(item->data(1).isEmpty())
{
height=img.height()+2;
}
else
{
height=img.height()+2+fmetrics.height()*qRound(fme trics.width(item->data(1))/width);
if(fmetrics.width(item->data(1))%width>0)
height+=fmetrics.height();
}
qDebug("w:%d h:%d", width, height);
return QSize(width, height+2);
}

returned width is -1 :| i dont get it :| Do I need to reimplement anything else? QStyleOptionViewItem &option for painting is get from viewOptions() ? ? ? Items with descriptions aren't even painted :|

UPDATE: option.rect.width() is -1 only for items with description :| Why is that?

wysota
14th March 2006, 16:24
But what returns -1? How do you set your model? Do you use a standard view or a subclass?

naresh
14th March 2006, 17:21
Here is my changed sizeHint:


QSize rosterDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
rosterItem *item = static_cast<rosterItem*>(index.internalPointer());

QFontMetrics fmetrics=option.fontMetrics;
QImage img=static_cast<rosterItem*>(index.internalPointer())->image();

int width=option.rect.width(),
height, iheight=img.height(),
nheight=fmetrics.height(),
dheight,
swidth=fmetrics.width(item->data(1)),
lines=ceil((float)fmetrics.width(item->data(1))/(float)width),
descrHeight=lines*nheight;

qDebug("string width:\t%d", swidth);
qDebug("image height:\t%d", iheight);
qDebug("string height:\t%d", nheight);
qDebug("x:\t%d", option.rect.x());
qDebug("y:\t%d", option.rect.y());
qDebug("lines:\t%d", lines);
qDebug("descr height:\t%d", descrHeight);

if(iheight>nheight)
height=iheight+2;
// height=iheight+descrHeight+2;
else
height=nheight+2;
// height=nheight+2+descrHeight+2;


qDebug("w:%d h:%d", width, height+descrHeight);
// return QSize(width, height+descrHeight);
return QSize(width, height);
}

It behaves realy strange :| When i replace last line with "return QSize(width, height);" it qDebug prints proper data, example:


string width: 600
image height: 16
string height: 14
x: 0
y: 18
lines: 4
descr height: 56
w:162 h:74

but when trying to return real required height (height+descrHeight) i get output like this:


string width: 268
image height: 16
string height: 14
x: 0
y: 0
lines: -268
descr height: -3752
w:-1 h:-3734
string width: 268
image height: 16
string height: 14
x: 0
y: 144
lines: 1
descr height: 14
w:824 h:32

I recive sizeHint for same item with description twice, one correct and one incorrect... item isn't painted at all :| normal item (group, or with out description) I recive correct data once... Any idea why is that?

wysota
14th March 2006, 19:55
What does fmetrics.height() return? and fmetrics.width(...)?

naresh
14th March 2006, 19:57
fmetrics.height() is string height and fmetrics.width(...) is string width lines in qDebug output

wysota
14th March 2006, 20:01
Looks like options.rect is incorrect. Do you use a standard view? What model do you use?

naresh
14th March 2006, 20:05
I'm using standard QTreeView. I'm using my custom model based on QAbstractItemModel, and no i didn't reimplement visualRect in it. And here is new sizeHint... it seems to calculate better but painting is worse :|


QSize rosterDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
QRect tmp=option.fontMetrics.boundingRect(option.rect.x( ), option.rect.y(), option.rect.width(), 1000, Qt::AlignLeft|Qt::AlignTop|Qt::TextWordWrap, index.model()->data(index, DescriptionRole).toString());
QImage img=index.model()->data(index, Qt::DecorationRole).value<QImage>();
int height;

if(tmp.height())
{
height=img.height()+tmp.height()+2;
}
else
{
height=img.height()+2;
}

qDebug("%d %d", option.rect.width(), height);

return QSize(option.rect.width(), height);
}

wysota
14th March 2006, 20:09
Could you explain "better" and "worse"?

naresh
14th March 2006, 20:27
Well better calculating means that size is now as i need (as i can see after calling painter->drawRect() ) and painting. And the worse is seen on screen. I dont know why but image isn't painted anymore (well ill fix it somehow) but this huge gap :| I dont know where is it from :|

I'm putting sources in attachment. Could you take a look at them?

naresh
15th March 2006, 19:15
I had to remove source code, here is new one (fixed a bit btw). Could you take a look at it?

naresh
16th March 2006, 18:46
Ok i have an idea how to calculate y position for all items... but only thing I need is to pass QTreeView::verticalOffset() (whitch is virtual protected)... best way I see is passing it with QStyleOptionViewItem (to QItemDelegate::paint(...)). Any idea how to do that?

wysota
17th March 2006, 13:32
Ok, I think I know what wrong. Looks like the view doesn't ask for the sizeHint each time it is resized, but only when an item changes. So you have to force the model to emit layoutChanged() on every view resize. Unfortunately you can't do it in the delegate, you should probably install an event filter on the view and provide a wrapper method for the model, which will emit layoutChanged() whenever the width of the view changes. It should be enough for your items to resize properly.

naresh
17th March 2006, 15:04
I checked throu whole painting (from view to delegate) and it paints wrong becouse of QTreeView::paintEvent(...). It calculates y position of each item depending on verticalStepsPerItem(). It can't be never calculated well becouse items have different heights... I've reimplemented this method but atm i have one problem... verticalScrollBar can move slider under all items. So now i don't know how to control verticalScrollBar. I've tried hiding it when viewport height is >= sizeHint height but there always left gray space for scroll bar. here is some code. Changing maximum for scrollBar causes scrollbar appear and disappear and so on... Also this painting seems to be really slow... Any ideas how to make it faster and control scrollbar? I'm placing source code to see what i have already done (and what am i missing)

EDIT: Another strange thing... It seems that items with descr have bigger range, i mean tooltip for those items is shown even if i place cursor on item under it :|

naresh
19th March 2006, 15:46
At least, after about a week of work it works like it should. First of all i've read whole thread few times to get it how was it painted before. It was taking width stright from viewport not from QStyleOptionViewItem. So i've added int width into delegate and method setWidth(int). I've reimplemented only resizeEvent for my rosterWidget class calling QTreeView::resizeEvent after setting width for delegate, and emiting layoutChanged for model (by my method emitLayoutChanged()). Delegate calculates sizeHint depending on width. I also added after every collaspe/expand item setting width (becouse scrollbar may appear and the viewport may resize without resizing widget). Now it paints and update well... As i expected. Thank you wysota for all your precious tips. Without them i would never make it.