Page 1 of 2 12 LastLast
Results 1 to 20 of 37

Thread: [Qt4] Noob and custom Item Delegate

  1. #1
    Join Date
    Feb 2006
    Location
    Warsaw, Poland
    Posts
    45
    Thanks
    1
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11 Windows

    Question [Qt4] Noob and custom Item Delegate

    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:
    Qt Code:
    1. void rosterDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
    2. {
    3. painter->setRenderHint(QPainter::TextAntialiasing);
    4. painter->setPen(Qt::NoPen);
    5.  
    6. if (option.state & QStyle::State_Selected)
    7. painter->setBrush(option.palette.highlight());
    8. else
    9. painter->setBrush(QBrush(Qt::white));
    10.  
    11. QTextOption textOption;
    12. textOption.setWrapMode(QTextOption::WordWrap);
    13.  
    14. QSize sizehint=sizeHint(option, index);
    15. int width=Qxygen->viewWidth();
    16. int height=ceil((sizehint.width()*sizehint.height())/width);
    17.  
    18. rosterItem *item = static_cast<rosterItem*>(index.internalPointer());
    19.  
    20. painter->drawText(QRectF(option.rect.x(), option.rect.y(), width, height), /* FROM WHERE GET THAT TEXT? */, textOption);
    21. }
    To copy to clipboard, switch view to plain text mode 

    here is my modelView data
    Qt Code:
    1. QVariant rosterView::data(const QModelIndex &index, int role) const
    2. {
    3. if (!index.isValid())
    4. return QVariant();
    5.  
    6. if (role == Qt::DisplayRole)
    7. {
    8. rosterItem *item = static_cast<rosterItem*>(index.internalPointer());
    9.  
    10. if(descr && !(item->isGroup())) // CHECKS IF VIEW HAS TO SHOW ITEM DESCRIPTION AND ITEM ISN'T GROUP - GROUPS DOESN'T NEED DESCRIPTION
    11. {
    12. if((item->data(1)).isEmpty()) return item->data(index.column());
    13. else return QString(item->data(index.column()))+"\n"+QString(item->data(1));
    14. }
    15. else
    16. {
    17. return item->data(index.column());
    18. }
    19. }
    20. else if(role == Qt::DecorationRole)
    21. {
    22. rosterItem *item = static_cast<rosterItem*>(index.internalPointer());
    23. if(item->isGroup())
    24. {
    25. if(item->isExpanded())
    26. {
    27. return QIcon(":expanded.png");
    28. }
    29. else
    30. {
    31. return QIcon(":collapsed.png");
    32. }
    33. }
    34. else
    35. {
    36. return QIcon(":dnd.png");
    37. }
    38. }
    39. else
    40. {
    41. return QVariant();
    42. }
    43. }
    To copy to clipboard, switch view to plain text mode 

    Now i have no idea how to make my delegate paint icon and text (in one column). Any suggestion/help?
    Last edited by naresh; 13th March 2006 at 11:36.

  2. #2
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,363
    Thanks
    3
    Thanked 5,012 Times in 4,791 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: [Qt4] Noob and custom Item Delegate

    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.

  3. #3
    Join Date
    Feb 2006
    Location
    Warsaw, Poland
    Posts
    45
    Thanks
    1
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: [Qt4] Noob and custom Item Delegate

    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?

  4. #4
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,363
    Thanks
    3
    Thanked 5,012 Times in 4,791 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: [Qt4] Noob and custom Item Delegate

    You might want to take a look at QStyleOptionViewItem 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).

    Qt Code:
    1. void ColumnChartView::drawRowNames( QPainter * p ) {
    2. int itemwidth = itemWidth();
    3. int seriesCount = model()->columnCount();
    4. int columnWidth = itemWidth()/seriesCount;
    5. int maxh = chartSize().height();
    6. int valueSpan = _maxVal - _minVal;
    7. uint rowHeight = (_flags & XTitle) ? _canvasVMargin-QFontMetrics(font()).height()-2 : _canvasVMargin;
    8. p->save();
    9. for(int i=0;i<model()->rowCount(rootIndex());i++) {
    10. QRect rect(qRound(_canvasHMargin+itemwidth/4+i*itemwidth*3/2), maxh+_canvasVMargin, itemwidth, rowHeight);
    11. QStyleOptionViewItem opt = getOptionsForRowLabel(i);
    12. p->setFont(opt.font);
    13. p->setPen(opt.palette.color(QPalette::Normal, QPalette::Text));
    14. p->drawText(rect,opt.displayAlignment|Qt::TextWordWrap,QAbstractItemDelegate::elidedText(fontMetrics(), rect.width(),Qt::ElideRight,model()->headerData(i, Qt::Vertical).toString()));
    15. }
    16. p->restore();
    17. }
    To copy to clipboard, switch view to plain text mode 

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

    Just for completeness:

    Qt Code:
    1. QStyleOptionViewItem ColumnChartView::getOptionsForRowLabel( int row ) {
    2. QStyleOptionViewItem opt = viewOptions();
    3. opt.displayAlignment |= Qt::AlignHCenter;
    4. opt.displayAlignment &= ~Qt::AlignVCenter;
    5. opt.displayAlignment |= Qt::AlignTop;
    6. QVariant value;
    7. value = model()->headerData(row, Qt::Vertical, Qt::FontRole);
    8. if(value.isValid())
    9. opt.font = qvariant_cast<QFont>(value);
    10. value = model()->headerData(row, Qt::Vertical, Qt::TextColorRole);
    11. if(value.isValid() && qvariant_cast<QColor>(value).isValid())
    12. opt.palette.setColor(QPalette::Text, qvariant_cast<QColor>(value));
    13. return opt;
    14. }
    To copy to clipboard, switch view to plain text mode 

  5. #5
    Join Date
    Feb 2006
    Location
    Warsaw, Poland
    Posts
    45
    Thanks
    1
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: [Qt4] Noob and custom Item Delegate

    And when should i call drawRowNames?

  6. #6
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,363
    Thanks
    3
    Thanked 5,012 Times in 4,791 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: [Qt4] Noob and custom Item Delegate

    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).

  7. #7
    Join Date
    Feb 2006
    Location
    Warsaw, Poland
    Posts
    45
    Thanks
    1
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: [Qt4] Noob and custom Item Delegate

    Well I've updated my delegate paint routine and still result is blank... Here it is:

    Qt Code:
    1. void rosterDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
    2. {
    3. painter->setRenderHint(QPainter::TextAntialiasing);
    4. painter->setPen(Qt::NoPen);
    5.  
    6. if (option.state & QStyle::State_Selected)
    7. painter->setBrush(option.palette.highlight());
    8. else
    9. painter->setBrush(QBrush(Qt::white));
    10.  
    11. QTextOption textOption;
    12. textOption.setWrapMode(QTextOption::WordWrap);
    13.  
    14. rosterItem *item = static_cast<rosterItem*>(index.internalPointer());
    15.  
    16. int width=Qxygen->viewWidth(), height;
    17.  
    18. QFontMetrics fmetrics=Qxygen->fontMetrics();
    19.  
    20. if(item->data(1).isEmpty())
    21. {
    22. height=fmetrics.height();
    23. }
    24. else
    25. {
    26. height=fmetrics.height()+fmetrics.height()*ceil(fmetrics.width(item->data(1))/width);
    27. }
    28.  
    29. QRect rect(option.rect.x(), option.rect.y(), width, height);
    30.  
    31. painter->drawText(rect,Qt::TextWordWrap,QAbstractItemDelegate::elidedText(static_cast<const QFontMetrics&>(Qxygen->roster()->fontMetrics()), rect.width(),Qt::ElideRight,Qxygen->model()->data(index, Qt::DisplayRole).toString()));
    32.  
    33. printf("Width: %d Height:%d\n", width, height);
    34. }
    To copy to clipboard, switch view to plain text mode 

    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
    Last edited by naresh; 13th March 2006 at 16:55.

  8. #8
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,363
    Thanks
    3
    Thanked 5,012 Times in 4,791 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: [Qt4] Noob and custom Item Delegate

    Qt Code:
    1. painter->setPen(Qt::NoPen);
    To copy to clipboard, switch view to plain text mode 

    How do you expect to paint anything without a pen?

  9. #9
    Join Date
    Feb 2006
    Location
    Warsaw, Poland
    Posts
    45
    Thanks
    1
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: [Qt4] Noob and custom Item Delegate

    Ok i've made even painting of icon, but it doesn't paint with the height i requested :|

    Here's code:
    Qt Code:
    1. void rosterDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
    2. {
    3. painter->setRenderHint(QPainter::TextAntialiasing);
    4. //painter->setPen(Qt::NoPen);
    5.  
    6. if (option.state == QStyle::State_Selected)
    7. painter->setBrush(option.palette.highlight());
    8. else
    9. painter->setBrush(QBrush(Qt::white));
    10.  
    11. QTextOption textOption;
    12. textOption.setWrapMode(QTextOption::WordWrap);
    13.  
    14. rosterItem *item = static_cast<rosterItem*>(index.internalPointer());
    15.  
    16. int width=Qxygen->viewWidth(), height;
    17.  
    18. QFontMetrics fmetrics=Qxygen->fontMetrics();
    19.  
    20. if(item->data(1).isEmpty())
    21. {
    22. height=fmetrics.height();
    23. }
    24. else
    25. {
    26. height=fmetrics.height()+fmetrics.height()*qRound(fmetrics.width(item->data(1))/width);
    27. if(fmetrics.width(item->data(1))%width>0)
    28. height+=14;
    29. }
    30.  
    31. printf("Width: %d Height:%d\n", width, height);
    32.  
    33. QImage img=Qxygen->model()->data(index, Qt::DecorationRole).value<QImage>();
    34.  
    35. QRect irect(option.rect.x(), option.rect.y(), img.width(), img.height());
    36. QRect rect(option.rect.x()+img.width()+2, option.rect.y(), width-img.width()-2, height);
    37.  
    38. opt.setWrapMode(QTextOption::WordWrap);
    39. opt.setAlignment(Qt::AlignTop|Qt::AlignLeft);
    40.  
    41. painter->drawImage(irect, img);
    42. // painter->drawText(rect, Qxygen->model()->data(index, Qt::DisplayRole).toString(), opt);
    43. painter->drawText(rect, Qt::TextWordWrap|Qt::AlignLeft|Qt::AlignTop, Qxygen->model()->data(index, Qt::DisplayRole).toString());
    44. // painter->drawText(rect,Qt::TextWordWrap,elidedText(static_cast<const QFontMetrics&>(Qxygen->roster()->fontMetrics()), rect.width(),Qt::ElideRight,Qxygen->model()->data(index, Qt::DisplayRole).toString()));
    45. }
    To copy to clipboard, switch view to plain text mode 

    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?

  10. #10
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,363
    Thanks
    3
    Thanked 5,012 Times in 4,791 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: [Qt4] Noob and custom Item Delegate

    Quote Originally Posted by naresh
    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)?

  11. #11
    Join Date
    Feb 2006
    Location
    Warsaw, Poland
    Posts
    45
    Thanks
    1
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: [Qt4] Noob and custom Item Delegate

    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" ? ? ?

  12. #12
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,363
    Thanks
    3
    Thanked 5,012 Times in 4,791 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: [Qt4] Noob and custom Item Delegate

    Quote Originally Posted by naresh
    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.
    Last edited by wysota; 13th March 2006 at 18:29.

  13. The following user says thank you to wysota for this useful post:

    naresh (13th March 2006)

  14. #13
    Join Date
    Feb 2006
    Location
    Warsaw, Poland
    Posts
    45
    Thanks
    1
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: [Qt4] Noob and custom Item Delegate

    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:

    Qt Code:
    1. void rosterDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
    2. {
    3. painter->setRenderHint(QPainter::TextAntialiasing);
    4. if (option.state==QStyle::State_Selected)
    5. painter->setBrush(Qxygen->roster()->palette().highlight());
    6. else
    7. painter->setBrush(QBrush(Qt::white));
    8.  
    9. QTextOption textOption;
    10. textOption.setWrapMode(QTextOption::WordWrap);
    11.  
    12. rosterItem *item = static_cast<rosterItem*>(index.internalPointer());
    13.  
    14. int width=Qxygen->viewWidth(), height;
    15.  
    16. QFontMetrics fmetrics=Qxygen->fontMetrics();
    17.  
    18. QImage img=Qxygen->model()->data(index, Qt::DecorationRole).value<QImage>();
    19.  
    20. QRect irect(option.rect.x(), option.rect.y()+2, img.width(), img.height());
    21. QRect nrect(option.rect.x()+img.width()+2, option.rect.y()+2, width-img.width()-2, fmetrics.height());
    22.  
    23. painter->drawImage(irect, img);
    24.  
    25. // CONTACT NAME
    26. painter->drawText(nrect, Qt::AlignLeft|Qt::AlignTop, elidedText(static_cast<const QFontMetrics&>(Qxygen->roster()->fontMetrics()), nrect.width(),Qt::ElideRight,item->data(0)));
    27.  
    28. if(!item->data(1).isEmpty())
    29. {
    30. int height=fmetrics.height()*qRound(fmetrics.width(item->data(1))/width);
    31. if(fmetrics.width(item->data(1))%width>0)
    32. height+=fmetrics.height();
    33.  
    34. QRect drect(option.rect.x(), option.rect.y()+img.height()+2, width, height);
    35. // DESCRIPTION
    36. painter->drawText(drect, Qt::TextWordWrap|Qt::AlignLeft|Qt::AlignTop, item->data(1));
    37. }
    38. }
    39.  
    40. QSize rosterDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
    41. {
    42. rosterItem *item = static_cast<rosterItem*>(index.internalPointer());
    43. int width=Qxygen->viewWidth(), height;
    44.  
    45. QFontMetrics fmetrics=Qxygen->fontMetrics();
    46.  
    47. QImage img(Qxygen->model()->data(index, Qt::DecorationRole).value<QImage>());
    48.  
    49. if(item->data(1).isEmpty())
    50. {
    51. height=img.height()+2;
    52. }
    53. else
    54. {
    55. height=img.height()+2+fmetrics.height()*qRound(fmetrics.width(item->data(1))/width);
    56. printf("%d %d\n", height, qRound(fmetrics.width(item->data(1))/width));
    57. if(fmetrics.width(item->data(1))%width>0)
    58. height+=fmetrics.height();
    59. }
    60.  
    61. return QSize(width, height+2);
    62. }
    To copy to clipboard, switch view to plain text mode 

    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 :|

  15. #14
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,363
    Thanks
    3
    Thanked 5,012 Times in 4,791 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: [Qt4] Noob and custom Item Delegate

    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.

  16. #15
    Join Date
    Feb 2006
    Location
    Warsaw, Poland
    Posts
    45
    Thanks
    1
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: [Qt4] Noob and custom Item Delegate

    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

  17. #16
    Join Date
    Feb 2006
    Location
    Warsaw, Poland
    Posts
    45
    Thanks
    1
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: [Qt4] Noob and custom Item Delegate

    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
    Attached Images Attached Images

  18. #17
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,363
    Thanks
    3
    Thanked 5,012 Times in 4,791 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: [Qt4] Noob and custom Item Delegate

    Does the view ask the delegate for the sizeHint after resize? (use qDebug to check that out).

  19. #18
    Join Date
    Feb 2006
    Location
    Warsaw, Poland
    Posts
    45
    Thanks
    1
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: [Qt4] Noob and custom Item Delegate

    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 :|
    Attached Images Attached Images
    Last edited by naresh; 14th March 2006 at 06:08.

  20. #19
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,363
    Thanks
    3
    Thanked 5,012 Times in 4,791 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: [Qt4] Noob and custom Item Delegate

    Quote Originally Posted by naresh
    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?
    Attached Files Attached Files
    Last edited by wysota; 14th March 2006 at 11:43. Reason: Attached an example project

  21. #20
    Join Date
    Feb 2006
    Location
    Warsaw, Poland
    Posts
    45
    Thanks
    1
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: [Qt4] Noob and custom Item Delegate

    Ok I've added before return in sizeHint something like this:

    Qt Code:
    1. qDebug("w:%d h%d", width, height)
    To copy to clipboard, switch view to plain text mode 

    And in paint at end something like this:

    Qt Code:
    1. Qxygen->model()->setData(index, sizeHint(option,index), Qt::SizeHintRole);
    To copy to clipboard, switch view to plain text mode 

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

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.