Page 2 of 2 FirstFirst 12
Results 21 to 37 of 37

Thread: [Qt4] Noob and custom Item Delegate

  1. #21
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 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
    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 
    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).

  2. #22
    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'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?

  3. #23
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 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

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

  4. #24
    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

    Here is "fixed" code for delegate

    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(option.palette.highlight());
    6. else
    7. painter->setBrush(QBrush(Qt::white));
    8.  
    9. rosterItem *item = static_cast<rosterItem*>(index.internalPointer());
    10.  
    11. int width=sizeHint(option,index).width(), height;
    12.  
    13. QFontMetrics fmetrics=option.fontMetrics;
    14.  
    15. QImage img=static_cast<rosterItem*>(index.internalPointer())->image();
    16.  
    17. QRect irect(option.rect.x(), option.rect.y()+2, img.width(), img.height());
    18. QRect nrect(option.rect.x()+img.width()+2, option.rect.y()+2, width-img.width()-2, fmetrics.height());
    19.  
    20. painter->drawImage(irect, img);
    21.  
    22. // CONTACT NAME
    23. painter->drawText(nrect, Qt::AlignLeft|Qt::AlignTop, elidedText(fmetrics, nrect.width(),Qt::ElideRight,item->data(0)));
    24.  
    25. if(!item->data(1).isEmpty())
    26. {
    27. int height=fmetrics.height()*qRound(fmetrics.width(item->data(1))/width);
    28. if(fmetrics.width(item->data(1))%width>0)
    29. height+=fmetrics.height();
    30.  
    31. QRect drect(option.rect.x()+1, option.rect.y()+img.height()+2, width, height);
    32. // DESCRIPTION
    33. painter->drawText(drect, Qt::TextWordWrap|Qt::AlignLeft|Qt::AlignTop, item->data(1));
    34. }
    35. }
    36.  
    37. QSize rosterDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
    38. {
    39. rosterItem *item = static_cast<rosterItem*>(index.internalPointer());
    40. int width=option.rect.width(), height;
    41.  
    42. QFontMetrics fmetrics=option.fontMetrics;
    43.  
    44. QImage img=static_cast<rosterItem*>(index.internalPointer())->image();
    45.  
    46. if(item->data(1).isEmpty())
    47. {
    48. height=img.height()+2;
    49. }
    50. else
    51. {
    52. height=img.height()+2+fmetrics.height()*qRound(fmetrics.width(item->data(1))/width);
    53. if(fmetrics.width(item->data(1))%width>0)
    54. height+=fmetrics.height();
    55. }
    56. qDebug("w:%d h:%d", width, height);
    57. return QSize(width, height+2);
    58. }
    To copy to clipboard, switch view to plain text mode 

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

  5. #25
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 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

    But what returns -1? How do you set your model? Do you use a standard view or a subclass?

  6. #26
    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

    Here is my changed sizeHint:

    Qt Code:
    1. QSize rosterDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
    2. {
    3. rosterItem *item = static_cast<rosterItem*>(index.internalPointer());
    4.  
    5. QFontMetrics fmetrics=option.fontMetrics;
    6. QImage img=static_cast<rosterItem*>(index.internalPointer())->image();
    7.  
    8. int width=option.rect.width(),
    9. height, iheight=img.height(),
    10. nheight=fmetrics.height(),
    11. dheight,
    12. swidth=fmetrics.width(item->data(1)),
    13. lines=ceil((float)fmetrics.width(item->data(1))/(float)width),
    14. descrHeight=lines*nheight;
    15.  
    16. qDebug("string width:\t%d", swidth);
    17. qDebug("image height:\t%d", iheight);
    18. qDebug("string height:\t%d", nheight);
    19. qDebug("x:\t%d", option.rect.x());
    20. qDebug("y:\t%d", option.rect.y());
    21. qDebug("lines:\t%d", lines);
    22. qDebug("descr height:\t%d", descrHeight);
    23.  
    24. if(iheight>nheight)
    25. height=iheight+2;
    26. // height=iheight+descrHeight+2;
    27. else
    28. height=nheight+2;
    29. // height=nheight+2+descrHeight+2;
    30.  
    31.  
    32. qDebug("w:%d h:%d", width, height+descrHeight);
    33. // return QSize(width, height+descrHeight);
    34. return QSize(width, height);
    35. }
    To copy to clipboard, switch view to plain text mode 

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

    Qt Code:
    1. string width: 600
    2. image height: 16
    3. string height: 14
    4. x: 0
    5. y: 18
    6. lines: 4
    7. descr height: 56
    8. w:162 h:74
    To copy to clipboard, switch view to plain text mode 

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

    Qt Code:
    1. string width: 268
    2. image height: 16
    3. string height: 14
    4. x: 0
    5. y: 0
    6. lines: -268
    7. descr height: -3752
    8. w:-1 h:-3734
    9. string width: 268
    10. image height: 16
    11. string height: 14
    12. x: 0
    13. y: 144
    14. lines: 1
    15. descr height: 14
    16. w:824 h:32
    To copy to clipboard, switch view to plain text mode 

    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?

  7. #27
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 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

    What does fmetrics.height() return? and fmetrics.width(...)?

  8. #28
    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

    fmetrics.height() is string height and fmetrics.width(...) is string width lines in qDebug output

  9. #29
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 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

    Looks like options.rect is incorrect. Do you use a standard view? What model do you use?
    Last edited by wysota; 14th March 2006 at 21:04.

  10. #30
    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'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 :|

    Qt Code:
    1. QSize rosterDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
    2. {
    3. 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());
    4. QImage img=index.model()->data(index, Qt::DecorationRole).value<QImage>();
    5. int height;
    6.  
    7. if(tmp.height())
    8. {
    9. height=img.height()+tmp.height()+2;
    10. }
    11. else
    12. {
    13. height=img.height()+2;
    14. }
    15.  
    16. qDebug("%d %d", option.rect.width(), height);
    17.  
    18. return QSize(option.rect.width(), height);
    19. }
    To copy to clipboard, switch view to plain text mode 

  11. #31
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 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

    Could you explain "better" and "worse"?

  12. #32
    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 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?
    Attached Images Attached Images
    Last edited by naresh; 15th March 2006 at 20:12.

  13. #33
    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 had to remove source code, here is new one (fixed a bit btw). Could you take a look at it?
    Attached Files Attached Files

  14. #34
    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 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?

  15. #35
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 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

    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.

  16. #36
    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 checked throu whole painting (from view to delegate) and it paints wrong becouse of QTreeView:aintEvent(...). 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 :|
    Attached Files Attached Files
    Last edited by naresh; 17th March 2006 at 19:22.

  17. #37
    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

    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.

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.