Results 1 to 8 of 8

Thread: Finding default delegate for QTreeView?

  1. #1
    Join Date
    Jun 2014
    Posts
    98
    Thanks
    43
    Thanked 4 Times in 4 Posts
    Platforms
    Windows

    Default Finding default delegate for QTreeView?

    tl;dr
    I am a PyQt user (Python binding of Qt), and am trying to figure out how Qt natively draws trees in QTreeView, as I am trying to recreate it using a custom delegate (QStyledItemDelegate applied to my view) just for instructive purposes. More specifically, I am viewing a QStandardItemModel using a QTreeView, and want to see the guts of the delegate that is used by default, but am having trouble finding the default 'paint' method. Is there a link to it?


    Details
    I am not very good at C++ (I'm a Python guy), and am having trouble figuring it out: I have been looking over the code at qtreeview.cpp but haven't actually found anything explicit where, for instance, the text is drawn corresponding to a particular item.

    Line 1389 has the `drawTree` method, which calls drawRow on line 1442:
    Qt Code:
    1. drawRow(painter, option, viewItems.at(i).index);
    To copy to clipboard, switch view to plain text mode 
    drawRow is defined starting on line 1473. Therein, I think we are reaching the guts, e.g., line 1679:
    Qt Code:
    1. d->delegateForIndex(modelIndex)->paint(painter, opt, modelIndex);
    To copy to clipboard, switch view to plain text mode 
    This suggests to me that that the delegate for the item associated with `modelIndex` is defined within `delegateForIndex`. But I have now hit the limits of my sleuthing, and am having trouble finding where this delegate, and its paint operation in particular, is defined.

    Any hints?

    ============
    Cross posted:
    http://stackoverflow.com/questions/3...treeview-in-qt
    Last edited by neuronet; 30th November 2015 at 01:01. Reason: linking to cross post at SO

  2. #2
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,230
    Thanks
    302
    Thanked 864 Times in 851 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: Finding default delegate for QTreeView?

    The actual default delegate and its painting methods are defined by the style in use; if you look in your qtbase/src/widgets/styles directory, you'll see files for all sorts of styles. You'll need to pick one that looks like it might be the style used by your platform, and search for "CE_ItemViewItem". You should find at least one occurrence in a drawControl method for the style (or its base class).

    I do not think this is the code that draws decorations on the tree, though - the node indicators, lines, etc. It's just the code that draws the index items themselves.

    You'll no doubt find the code ugly and confusing, but that's the nature of the beast when you are writing a platform-independent user interface toolkit.

  3. The following user says thank you to d_stranz for this useful post:

    neuronet (30th November 2015)

  4. #3
    Join Date
    Jun 2014
    Posts
    98
    Thanks
    43
    Thanked 4 Times in 4 Posts
    Platforms
    Windows

    Default Re: Finding default delegate for QTreeView?

    It seems the following snippet from qcommonstyle.cpp will repay careful study. What do you c++/qt gurus think? Is this the crux of the answer to my question?

    Qt Code:
    1. #ifndef QT_NO_ITEMVIEWS
    2. case CE_ItemViewItem:
    3. if (const QStyleOptionViewItemV4 *vopt = qstyleoption_cast<const QStyleOptionViewItemV4 *>(opt)) {
    4. p->save();
    5. p->setClipRect(opt->rect);
    6.  
    7. QRect checkRect = subElementRect(SE_ItemViewItemCheckIndicator, vopt, widget);
    8. QRect iconRect = subElementRect(SE_ItemViewItemDecoration, vopt, widget);
    9. QRect textRect = subElementRect(SE_ItemViewItemText, vopt, widget);
    10.  
    11. // draw the background
    12. proxy()->drawPrimitive(PE_PanelItemViewItem, opt, p, widget);
    13.  
    14. // draw the check mark
    15. if (vopt->features & QStyleOptionViewItemV2::HasCheckIndicator) {
    16. QStyleOptionViewItemV4 option(*vopt);
    17. option.rect = checkRect;
    18. option.state = option.state & ~QStyle::State_HasFocus;
    19.  
    20. switch (vopt->checkState) {
    21. case Qt::Unchecked:
    22. option.state |= QStyle::State_Off;
    23. break;
    24. case Qt::PartiallyChecked:
    25. option.state |= QStyle::State_NoChange;
    26. break;
    27. case Qt::Checked:
    28. option.state |= QStyle::State_On;
    29. break;
    30. }
    31. proxy()->drawPrimitive(QStyle::PE_IndicatorViewItemCheck, &option, p, widget);
    32. }
    33.  
    34. // draw the icon
    35. QIcon::Mode mode = QIcon::Normal;
    36. if (!(vopt->state & QStyle::State_Enabled))
    37. mode = QIcon::Disabled;
    38. else if (vopt->state & QStyle::State_Selected)
    39. mode = QIcon::Selected;
    40. QIcon::State state = vopt->state & QStyle::State_Open ? QIcon::On : QIcon::Off;
    41. vopt->icon.paint(p, iconRect, vopt->decorationAlignment, mode, state);
    42.  
    43. // draw the text
    44. if (!vopt->text.isEmpty()) {
    45. QPalette::ColorGroup cg = vopt->state & QStyle::State_Enabled
    46. ? QPalette::Normal : QPalette::Disabled;
    47. if (cg == QPalette::Normal && !(vopt->state & QStyle::State_Active))
    48. cg = QPalette::Inactive;
    49.  
    50. if (vopt->state & QStyle::State_Selected) {
    51. p->setPen(vopt->palette.color(cg, QPalette::HighlightedText));
    52. } else {
    53. p->setPen(vopt->palette.color(cg, QPalette::Text));
    54. }
    55. if (vopt->state & QStyle::State_Editing) {
    56. p->setPen(vopt->palette.color(cg, QPalette::Text));
    57. p->drawRect(textRect.adjusted(0, 0, -1, -1));
    58. }
    59.  
    60. d->viewItemDrawText(p, vopt, textRect);
    61. }
    62.  
    63. // draw the focus rect
    64. if (vopt->state & QStyle::State_HasFocus) {
    65. o.QStyleOption::operator=(*vopt);
    66. o.rect = proxy()->subElementRect(SE_ItemViewItemFocusRect, vopt, widget);
    67. o.state |= QStyle::State_KeyboardFocusChange;
    68. o.state |= QStyle::State_Item;
    69. QPalette::ColorGroup cg = (vopt->state & QStyle::State_Enabled)
    70. ? QPalette::Normal : QPalette::Disabled;
    71. o.backgroundColor = vopt->palette.color(cg, (vopt->state & QStyle::State_Selected)
    72. ? QPalette::Highlight : QPalette::Window);
    73. proxy()->drawPrimitive(QStyle::PE_FrameFocusRect, &o, p, widget);
    74. }
    75.  
    76. p->restore();
    77. }
    78. break;
    To copy to clipboard, switch view to plain text mode 

    Not exactly sure what 'd' is, but rawing the text, for instance, seems it would go as follows:

    Qt Code:
    1. void QCommonStylePrivate::viewItemDrawText(QPainter *p, const QStyleOptionViewItemV4 *option, const QRect &rect) const
    2. {
    3. const QWidget *widget = option->widget;
    4. const int textMargin = proxyStyle->pixelMetric(QStyle::PM_FocusFrameHMargin, 0, widget) + 1;
    5.  
    6. QRect textRect = rect.adjusted(textMargin, 0, -textMargin, 0); // remove width padding
    7. const bool wrapText = option->features & QStyleOptionViewItemV2::WrapText;
    8. QTextOption textOption;
    9. textOption.setWrapMode(wrapText ? QTextOption::WordWrap : QTextOption::ManualWrap);
    10. textOption.setTextDirection(option->direction);
    11. textOption.setAlignment(QStyle::visualAlignment(option->direction, option->displayAlignment));
    12. QTextLayout textLayout;
    13. textLayout.setTextOption(textOption);
    14. textLayout.setFont(option->font);
    15. textLayout.setText(option->text);
    16.  
    17. viewItemTextLayout(textLayout, textRect.width());
    18.  
    19. QString elidedText;
    20. qreal height = 0;
    21. qreal width = 0;
    22. int elidedIndex = -1;
    23. const int lineCount = textLayout.lineCount();
    24. for (int j = 0; j < lineCount; ++j) {
    25. const QTextLine line = textLayout.lineAt(j);
    26. if (j + 1 <= lineCount - 1) {
    27. const QTextLine nextLine = textLayout.lineAt(j + 1);
    28. if ((nextLine.y() + nextLine.height()) > textRect.height()) {
    29. int start = line.textStart();
    30. int length = line.textLength() + nextLine.textLength();
    31. const QStackTextEngine engine(textLayout.text().mid(start, length), option->font);
    32. elidedText = engine.elidedText(option->textElideMode, textRect.width());
    33. height += line.height();
    34. width = textRect.width();
    35. elidedIndex = j;
    36. break;
    37. }
    38. }
    39. if (line.naturalTextWidth() > textRect.width()) {
    40. int start = line.textStart();
    41. int length = line.textLength();
    42. const QStackTextEngine engine(textLayout.text().mid(start, length), option->font);
    43. elidedText = engine.elidedText(option->textElideMode, textRect.width());
    44. height += line.height();
    45. width = textRect.width();
    46. elidedIndex = j;
    47. break;
    48. }
    49. width = qMax<qreal>(width, line.width());
    50. height += line.height();
    51. }
    52.  
    53. const QRect layoutRect = QStyle::alignedRect(option->direction, option->displayAlignment,
    54. QSize(int(width), int(height)), textRect);
    55. const QPointF position = layoutRect.topLeft();
    56. for (int i = 0; i < lineCount; ++i) {
    57. const QTextLine line = textLayout.lineAt(i);
    58. if (i == elidedIndex) {
    59. qreal x = position.x() + line.x();
    60. qreal y = position.y() + line.y() + line.ascent();
    61. p->save();
    62. p->setFont(option->font);
    63. p->drawText(QPointF(x, y), elidedText);
    64. p->restore();
    65. break;
    66. }
    67. line.draw(p, position);
    68. }
    69. }
    To copy to clipboard, switch view to plain text mode 

    Am I in the right ballpark, folks? I feel I am finally getting close after many days of sleuthing.
    Last edited by neuronet; 3rd December 2015 at 04:48.

  5. #4
    Join Date
    Jun 2014
    Posts
    98
    Thanks
    43
    Thanked 4 Times in 4 Posts
    Platforms
    Windows

    Default Re: Finding default delegate for QTreeView?

    am posting summary but still working on it sorry will post later...add it here....couldn't figure out how to delete this post, I had added it but didn't like it so cut it and will add back what I had later....
    Last edited by neuronet; 7th December 2015 at 20:34.

  6. #5
    Join Date
    Jun 2014
    Posts
    98
    Thanks
    43
    Thanked 4 Times in 4 Posts
    Platforms
    Windows

    Default Re: Finding default delegate for QTreeView?

    So in sum, yes, it is all about qcommonstyle.cpp and the code snippets I posted above (with some additional stuff too). In some caseis it is not very useful to track the delegate through to its elementary painting operations, but in some cases it is, and the only way to know for sure is to do it for each subelement of interest.

    I'll be posting a very long answer along those lines over at Stack Overflow at the link in OP.

  7. #6
    Join Date
    Jun 2014
    Posts
    98
    Thanks
    43
    Thanked 4 Times in 4 Posts
    Platforms
    Windows

    Default Re: Finding default delegate for QTreeView?

    So, my answer ended up being about 6 pages long, and I posted it at STack Overflow:
    http://stackoverflow.com/a/34215918/1886357


    Here is the "summary" section of the answer:
    If you want to access the underlying painting mechanics for the default delegate, you will end up studying the implementation of `QStyle.drawControl()` in `qcommonstyle.cpp`, a 6000-line beast of a file. This exercise can be very helpful for figuring out the exact procedures used to calculate sizes and draw the primitive graphical elements that items contain. Sometimes, however, this beast can be downright scary and unhelpful, like when it comes to dealing with word wrap. In those cases, you will probably just have to figure out a custom implementation of the desired functionality for your delegate.

    Finally, now that we've seen a big-picture view of how things work, we are finally ready to appreciate how helpful the documentation for `QStyle` is, in particular the section Styles in Item Views. There, we find the following revelatory love nugget that nicely sums things up:

    > The painting of items in views is performed by a delegate. Qt’s
    > default delegate, `QStyledItemDelegate`, is also used for calculating
    > bounding rectangles of items (and their sub-elements) …When
    > `QStyledItemDelegate` paints its items, it draws `CE_ItemViewItems`…When
    > implementing a style to customize drawing of item views, you need to
    > check the implementation of `QCommonStyle` (and any other subclasses
    > from which your style inherits). This way, you find out which and how
    > other style elements are already painted, and you can then reimplement
    > the painting of elements that should be drawn differently.

    So basically the answer to the original post is, "What they said."

  8. The following user says thank you to neuronet for this useful post:

    d_stranz (17th December 2015)

  9. #7
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,230
    Thanks
    302
    Thanked 864 Times in 851 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: Finding default delegate for QTreeView?

    trying to figure out how Qt natively draws trees in QTreeView, as I am trying to recreate it using a custom delegate (QStyledItemDelegate applied to my view) just for instructive purposes.
    So which do you feel, instructed or beaten into submission?

  10. #8
    Join Date
    Jun 2014
    Posts
    98
    Thanks
    43
    Thanked 4 Times in 4 Posts
    Platforms
    Windows

    Default Re: Finding default delegate for QTreeView?

    Quote Originally Posted by d_stranz View Post
    So which do you feel, instructed or beaten into submission?
    Yes. I learned more about Qt in the past two weeks than in the past six months, I think, but also feel like I got pulled through a woodchipper.

Similar Threads

  1. Replies: 0
    Last Post: 23rd April 2015, 17:27
  2. QTreeView default drag action
    By onamatic in forum Qt Programming
    Replies: 2
    Last Post: 1st March 2010, 07:37
  3. QTreeView Delegate
    By ^NyAw^ in forum Qt Programming
    Replies: 3
    Last Post: 23rd June 2009, 09:10
  4. Default delegate displays empty QLineEdit?
    By andy.fillebrown in forum Qt Programming
    Replies: 3
    Last Post: 16th April 2009, 13:13
  5. No delegate for 1 column in QTreeView
    By mace in forum Qt Programming
    Replies: 1
    Last Post: 15th February 2007, 10:55

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.