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

Thread: How to simplify a complex item delegate?

  1. #1
    Join Date
    Aug 2012
    Location
    Wrocław, Poland
    Posts
    25
    Thanks
    3
    Qt products
    Qt4
    Platforms
    Windows

    Question How to simplify a complex item delegate?

    I have a QListView which paints (and measures) its items with a custom QStyledItemDelegate.

    But over time the item grew quite complex. When it was still a thumbnail and to the right of it a bunch of header/value label pairs aligned in a column the code was long and ugly but it was still manageable. But when now I have to add some additional icons the measuring and painting code got really awful. It feels more than natural to use a custom QWidget instead since it can easily use all the goodies of UI Designer, styling and so on.

    However by reading documentation and tutorials I felt like it is the *View family of widgets that gets "more love" than the *Widget family. While my personal experience leads me to think that QAbstractItemModel-based approach to Model/View framework is actually quite limited and doing anything more than what Qt has thought about quickly becomes quite difficult.

    Or is there maybe some other approach to writing custom QStyledItemDelegate which deals with complexity better?

  2. #2
    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: How to simplify a complex item delegate?

    It really depends on what you want to do. For some cases it might be feasible to replace QListView with QDeclarativeView and implement the list in QML where it is much easier to code delegates. But again, maybe it is easy to do what you want with item views and you just need to restructure your code.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  3. #3
    Join Date
    Aug 2012
    Location
    Wrocław, Poland
    Posts
    25
    Thanks
    3
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: How to simplify a complex item delegate?

    Quote Originally Posted by wysota View Post
    It really depends on what you want to do.
    For example something like the Windows Media Player list view shown here. Or even its sub-case: just the album thumbnail with labels on the right. The more data you have the more difficult it gets to do it with QAbstractItemDelegate. Not to mention how styling gets difficult.

  4. #4
    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: How to simplify a complex item delegate?

    If you have a single constant layout then implementing such a delegate is trivial. I thought you wanted something more complex. Just bear in mind this is a table (or even a tree) and not a list.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  5. #5
    Join Date
    Aug 2012
    Location
    Wrocław, Poland
    Posts
    25
    Thanks
    3
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: How to simplify a complex item delegate?

    Quote Originally Posted by wysota View Post
    If you have a single constant layout then implementing such a delegate is trivial.
    I would not agree with that. Especially after writing such a delegate just few days ago (and mine had just a thumbnail + 2 pairs of header/value labels). It took me some time (OK, I'm know to Qt) and resulting code is long, difficult to understand and maintain. Even thou it contains mostly just calls to measuring functions. Adding another 2 labels or some extra icons, especially by someone else after some time would be really painful.

    And such layout code felt like a natural candidate for generalization and extraction as a separate class/function. With this question I was trying to know those generalization.

    Quote Originally Posted by wysota View Post
    I thought you wanted something more complex. Just bear in mind this is a table (or even a tree) and not a list.
    It is not really important. After all it was just an example.

  6. #6
    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: How to simplify a complex item delegate?

    Quote Originally Posted by Adam Badura View Post
    I would not agree with that. Especially after writing such a delegate just few days ago (and mine had just a thumbnail + 2 pairs of header/value labels). It took me some time (OK, I'm know to Qt) and resulting code is long, difficult to understand and maintain.
    Well, you have every right to disagree however in my opinion the delegate for the thumbnail and those three labels is around 3-6 lines long (depending how you choose to implement it).

    And such layout code felt like a natural candidate for generalization and extraction as a separate class/function. With this question I was trying to know those generalization.
    You can write such layout engine however in my opinion it is an overkill since your "layout" is static and always the same. Having a layout engine makes sense if you expect to have different layouts in every item or you expect that some pieces of data will change their visual position and the layout will have to be recalculated.


    It is not really important. After all it was just an example.
    On the contrary, this is very important. In a list you have to render the whole row in one go. With a table or a tree every column is rendered separately thus implementation of each delegate is greatly simplified. You have to choose proper tools for each job.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  7. #7
    Join Date
    Aug 2012
    Location
    Wrocław, Poland
    Posts
    25
    Thanks
    3
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: How to simplify a complex item delegate?

    Quote Originally Posted by wysota View Post
    Well, you have every right to disagree however in my opinion the delegate for the thumbnail and those three labels is around 3-6 lines long (depending how you choose to implement it).
    Could you provide an example? Since maybe I just did it in some very sub-optimal way.

    In my case it is a QTreeView but it could be limited to QListView as we are using it that way currently. There is a thumbnail in Qt::DecorationRole. To the right of it there are two text fields stacked vertically: "Name: ..." with value taken from Qt::DisplayRole and "Length: ..." with value from custom role. The header labels are aligned to the left, and the values are aligned to the left so there are two columns.

  8. #8
    Join Date
    Aug 2012
    Location
    Wrocław, Poland
    Posts
    25
    Thanks
    3
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: How to simplify a complex item delegate?

    Dear wysota, you wrote:

    Quote Originally Posted by wysota View Post
    If you have a single constant layout then implementing such a delegate is trivial.
    and

    Quote Originally Posted by wysota View Post
    Well, you have every right to disagree however in my opinion the delegate for the thumbnail and those three labels is around 3-6 lines long (depending how you choose to implement it).
    Since I found it highly questionable I asked for that simple thing:

    Quote Originally Posted by Adam Badura View Post
    Could you provide an example? Since maybe I just did it in some very sub-optimal way.

    In my case it is a QTreeView but it could be limited to QListView as we are using it that way currently. There is a thumbnail in Qt::DecorationRole. To the right of it there are two text fields stacked vertically: "Name: ..." with value taken from Qt::DisplayRole and "Length: ..." with value from custom role. The header labels are aligned to the left, and the values are aligned to the left so there are two columns.
    Over 10 days passed. You were here. And yet you did not provide those trivial 3-6 lines... Let others who come here with similar issue judge that...

  9. #9
    Join Date
    Jan 2006
    Location
    Germany
    Posts
    4,380
    Thanks
    19
    Thanked 1,005 Times in 913 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows Symbian S60
    Wiki edits
    5

    Default Re: How to simplify a complex item delegate?

    Let others who come here with similar issue judge that...
    Well it is because he don't want to write the delegate for you and one annoying thing is when people requesting code but didn't provide what they have tried so far. This leads to the conclusion - which my not be valid in every case - that nothing has be done so far... So I can understand him. And the attitude you are showing is not helpful either. (Beside, if someone has more than 28.000 posts and more then 4.000 thanks, which is the most here, he probably is a nice guy. In this case, I can confirm that)

    As to your problem: Have you seen the Star delegate Example? From there:
    Qt Code:
    1. void StarDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
    2. const QModelIndex &index) const
    3. {
    4. if (qVariantCanConvert<StarRating>(index.data())) {
    5. StarRating starRating = qVariantValue<StarRating>(index.data());
    6.  
    7. if (option.state & QStyle::State_Selected)
    8. painter->fillRect(option.rect, option.palette.highlight());
    9.  
    10. starRating.paint(painter, option.rect, option.palette,
    11. StarRating::ReadOnly);
    12. } else {
    13. QStyledItemDelegate::paint(painter, option, index);
    14. }
    15. }
    To copy to clipboard, switch view to plain text mode 
    Which total represent your example link of a music player.

  10. #10
    Join Date
    Aug 2012
    Location
    Wrocław, Poland
    Posts
    25
    Thanks
    3
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: How to simplify a complex item delegate?

    Quote Originally Posted by Lykurg View Post
    Which total represent your example link of a music player.
    It does not. The star sample skips the most important (for me) part: the thumbnail and stacked labels on the right of it. And that is what I actually want to achieve (the Windows Media Player sample was just first that same to my mind - and that I found - when trying to provide some sample). What I wanted to achieve I have described in the very first post (second paragraph) and in the one that asked explicitly for the "trivial code" (also second paragraph).

    By the way: In my Qt 4.8.4 when I build Examples and Demos with qmake -tp vc -r the resulting Visual Studio solution did not open cleanly in Visual Studio since some projects had same names and the solution didn't use its folders. Yet I believe this is only a "GUI issue". MS Build shouldn't care about it anyway. More important issue was that the star example wasn't build at all! It is not included in its "parent .pro file".

    I didn't post more details on my current state since I considered that irrelevant and "obfuscated" to much with particular details of my project while my investigations and research lead me to think it is a general issue rather than my specific one. But sure, I can give more details. This is how it looks now:

    Example.jpg

    It is a QTreeView (from historical reasons and for future extensions; for what it is now it could very well be just a QListView). The white header at the begining (with "Adam Badura") is a header with single column. Bellow are the items. The backgrounds alternate (although even-background is not visible here). Various states are represented with various background colors. On the left of each item there is a thumbnail (in this quickly-taken snapshot all thumbnails are same). To the right of it are the stacked labels (likely soon we will want to add at least two more labels). The green arrow is a quickly added icon. It does not align to anythig (yet).

    The view itself works in two modes. This is the "expanded" one. The "simple" one has shorter single-line items done mostly with default drawing. It is done by alternating item delegate. But I'm considering switching to alternating QTreeViews instead (that would just share single model) as it seems simpler and does not require use of apparently undocumented QTreeView::doItemsLayout() function.

    Now the crucial part of the code it auxiliary delegate function measureItem (it is my own function). It measures and lays out all the parts of the item and the item itself. Then I call it from QStyledItemDelegate::sizeHint (for the item size) and from QStyledItemDelegate::paint (which next just calls a bunch of drawing functions within the already computed rectangles). Code is following:

    Qt Code:
    1. void ElExtendedPlaylistEditorDelegate::measureItem(
    2. QStyleOptionViewItemV4 const& option,
    3. QStyle const* stylePtr,
    4. QModelIndex const& index,
    5. QRect& item,
    6. QRect& thumbnail,
    7. QRect& nameHeaderLabel,
    8. QRect& nameDataLabel,
    9. QRect& lengthHeaderLabel,
    10. QRect& lengthDataLabel,
    11. QRect& videoEffectImageRect
    12. ) const
    13. {
    14. // More or less arbitrarily selected values.
    15.  
    16. // Margins within the item in which components will be laid out.
    17. QMargins padding( 2, 2, 2, 2 );
    18. // Enough to show a reasonable icon.
    19. int minimumThumbnailHeight = 64;
    20. // HD aspect ratio.
    21. boost::rational< int > thumbnailAspectRatio( 1920, 1080 );
    22.  
    23. int thumbnailLabelsMargin =
    24. stylePtr->layoutSpacing(
    25. QSizePolicy::DefaultType,
    26. QSizePolicy::Label,
    27. Qt::Horizontal,
    28. &option,
    29. option.widget
    30. );
    31. if ( thumbnailLabelsMargin == -1 )
    32. thumbnailLabelsMargin = 5;
    33.  
    34. int labelsVerticalMargin =
    35. stylePtr->layoutSpacing(
    36. QSizePolicy::Label,
    37. QSizePolicy::Label,
    38. Qt::Vertical,
    39. &option,
    40. option.widget
    41. );
    42. if ( labelsVerticalMargin == -1 )
    43. labelsVerticalMargin = 2;
    44.  
    45. // Obtain/reformat some data.
    46.  
    47. EbTimecode length =
    48. index.data(
    49. sps::spsGUI::PlaylistModel::CustomRole::ITEM_LENGTH
    50. ).value< EbTimecode >();
    51. QString lengthString = length.getTimecodeString();
    52.  
    53.  
    54. // Measure components which are not flexible.
    55.  
    56. // Note that the measuring includes a space between header and data. This way
    57. // margin is scaled well with the font that is used rather than fixed to given
    58. // pixels value.
    59.  
    60. nameHeaderLabel =
    61. stylePtr->itemTextRect(
    62. option.fontMetrics,
    63. QRect(),
    64. Qt::AlignLeft | Qt::AlignBottom,
    65. ( option.state & QStyle::State_Enabled ) != 0,
    66. tr( "Name:" ) + " "
    67. );
    68.  
    69. nameDataLabel =
    70. stylePtr->itemTextRect(
    71. option.fontMetrics,
    72. QRect(),
    73. Qt::AlignLeft | Qt::AlignBottom,
    74. ( option.state & QStyle::State_Enabled ) != 0,
    75. option.text
    76. );
    77.  
    78. lengthHeaderLabel =
    79. stylePtr->itemTextRect(
    80. option.fontMetrics,
    81. QRect(),
    82. Qt::AlignLeft | Qt::AlignBottom,
    83. ( option.state & QStyle::State_Enabled ) != 0,
    84. tr( "Length:" ) + " "
    85. );
    86.  
    87. lengthDataLabel =
    88. stylePtr->itemTextRect(
    89. option.fontMetrics,
    90. QRect(),
    91. Qt::AlignLeft | Qt::AlignBottom,
    92. ( option.state & QStyle::State_Enabled ) != 0,
    93. lengthString
    94. );
    95.  
    96. // it will be changed after demo:)
    97. videoEffectImageRect = QRect( 0, 0, 30, 20 );
    98.  
    99. // Now start laying out the components with labels.
    100.  
    101. nameHeaderLabel.translate(
    102. -nameHeaderLabel.left(),
    103. -nameHeaderLabel.top()
    104. + option.rect.top()
    105. + padding.top()
    106. );
    107. nameDataLabel.translate(
    108. -nameDataLabel.left(),
    109. -nameDataLabel.top()
    110. + option.rect.top()
    111. + padding.top()
    112. );
    113.  
    114. Q_ASSERT( nameHeaderLabel.height() == nameDataLabel.height() );
    115. int nameJoinedLabelHeight =
    116. ( std::max )( nameHeaderLabel.height(), nameDataLabel.height() );
    117.  
    118. lengthHeaderLabel.translate(
    119. -lengthHeaderLabel.left(),
    120. -lengthHeaderLabel.top()
    121. + option.rect.top()
    122. + padding.top()
    123. + nameJoinedLabelHeight
    124. + labelsVerticalMargin
    125. );
    126. lengthDataLabel.translate(
    127. -lengthDataLabel.left(),
    128. -lengthDataLabel.top()
    129. + option.rect.top()
    130. + padding.top()
    131. + nameJoinedLabelHeight
    132. + labelsVerticalMargin
    133. );
    134. videoEffectImageRect.translate(
    135. -videoEffectImageRect.left(),
    136. -videoEffectImageRect.top()
    137. + option.rect.top()
    138. + padding.top()
    139. + nameJoinedLabelHeight
    140. + labelsVerticalMargin
    141. + labelsVerticalMargin
    142. );
    143.  
    144. Q_ASSERT( lengthHeaderLabel.height() == lengthDataLabel.height() );
    145. int lengthJoinedLabelHeight =
    146. ( std::max )( lengthHeaderLabel.height(), lengthDataLabel.height() );
    147.  
    148. int headersWidth =
    149. ( std::max )( nameHeaderLabel.width(), lengthHeaderLabel.width() );
    150.  
    151. nameHeaderLabel.translate(
    152. option.rect.left()
    153. + padding.left(),
    154. 0
    155. );
    156. nameDataLabel.translate(
    157. option.rect.left()
    158. + padding.left()
    159. + headersWidth,
    160. 0
    161. );
    162.  
    163. lengthHeaderLabel.translate(
    164. option.rect.left()
    165. + padding.left(),
    166. 0
    167. );
    168. lengthDataLabel.translate(
    169. option.rect.left()
    170. + padding.left()
    171. + headersWidth,
    172. 0
    173. );
    174. videoEffectImageRect.translate(
    175. option.rect.left()
    176. + padding.left()
    177. + headersWidth
    178. + lengthDataLabel.width(),
    179. 0
    180. );
    181.  
    182. int labelsWidth =
    183. headersWidth
    184. + ( std::max )( nameDataLabel.width(), lengthDataLabel.width() );
    185. int labelsHeight =
    186. nameJoinedLabelHeight
    187. + labelsVerticalMargin
    188. + lengthJoinedLabelHeight;
    189.  
    190.  
    191. // Now that the labels are laid out we have to include the thumbnail.
    192.  
    193. int thumbnailHeight =
    194. (std::max )( minimumThumbnailHeight, labelsHeight );
    195. auto thumbnailWidthExact = thumbnailAspectRatio * thumbnailHeight;
    196. int thumbnailWidth = boost::rational_cast< int >( thumbnailWidthExact );
    197.  
    198. Q_ASSERT( thumbnailHeight >= labelsHeight );
    199. int itemContentsHeight = thumbnailHeight;
    200.  
    201. int itemContentsWidth =
    202. thumbnailWidth
    203. + thumbnailLabelsMargin
    204. + labelsWidth;
    205.  
    206.  
    207. thumbnail.setCoords(
    208. option.rect.left()
    209. + padding.left(),
    210. option.rect.top()
    211. + padding.top(),
    212. option.rect.left()
    213. + padding.left()
    214. + thumbnailWidth,
    215. option.rect.top()
    216. + padding.top()
    217. + itemContentsHeight
    218. );
    219.  
    220. // Offset labels by the thumbnail width (plus margin).
    221.  
    222. nameHeaderLabel.translate(
    223. thumbnailWidth + thumbnailLabelsMargin,
    224. 0
    225. );
    226. nameDataLabel.translate(
    227. thumbnailWidth + thumbnailLabelsMargin,
    228. 0
    229. );
    230. lengthHeaderLabel.translate(
    231. thumbnailWidth + thumbnailLabelsMargin,
    232. 0
    233. );
    234. lengthDataLabel.translate(
    235. thumbnailWidth + thumbnailLabelsMargin,
    236. 0
    237. );
    238.  
    239. videoEffectImageRect.translate(
    240. thumbnailWidth + thumbnailLabelsMargin,
    241. 0
    242. );
    243.  
    244. // Finally item size itself.
    245.  
    246. item.setCoords(
    247. option.rect.left(),
    248. option.rect.top(),
    249. option.rect.left()
    250. + padding.left()
    251. + itemContentsWidth
    252. + padding.right(),
    253. option.rect.top()
    254. + padding.top()
    255. + itemContentsHeight
    256. + padding.bottom()
    257. );
    258. }
    To copy to clipboard, switch view to plain text mode 

    As can be seen obviously it is neither trivial nor 3-6 lines...

    And now consider that user requests a change and wants the "header labels" ("Name:" and "Length:") to be aligned to right rather than to left in its column. It can be done. But it requires a programmer who understands the code. While conceptually it should be just "changing an enum value" and I believe UI Designer would allow such change much easier. But since I have QTreeView I cannot design my items in UI Designer...

  11. #11
    Join Date
    Dec 2012
    Posts
    90
    Thanks
    5
    Thanked 20 Times in 18 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: How to simplify a complex item delegate?

    I have a crazy idea.

    What if you add to your delegate pointer to a shadow QWidget.
    Then you'll do all the custom layout in designer, and add resulting QWidget to your delegate.
    Then in paint event you apply necessary tweaks to the widget, and then render it using QWidget::render ()!

  12. The following user says thank you to lanz for this useful post:

    Adam Badura (20th February 2013)

  13. #12
    Join Date
    Jan 2006
    Location
    Germany
    Posts
    4,380
    Thanks
    19
    Thanked 1,005 Times in 913 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows Symbian S60
    Wiki edits
    5

    Default Re: How to simplify a complex item delegate?

    Quote Originally Posted by Adam Badura View Post
    It does not. The star sample skips the most important (for me) part: the thumbnail and stacked labels on the right of it.
    Ups, I call that selective perception... Right.

    Now the crucial part of the code
    Ok, you have a tree view: 1st column the image -> handled by the standard item delegate. 2nd column the labels. To simplify that and to extend it easily use loops e.g.
    Qt Code:
    1. QList<QPair<QString,QString> > labels; // a pair has "label:value"
    2. // max width of label description:
    3. int maxDescWidth = 0;
    4. foreach(QPair<QString,QString> l, labels)
    5. maxDescWidth = qMax(maxDescWidth, fontmetrics.width(l.first));
    6.  
    7. // then drawing
    8. int height = fontmetrics.height() + padding;
    9. for(int i = /*...*/) {
    10. painter->drawText(QRect(0,i*height, maxDescWidth, height), Qt::AlignRight, labels.at(i).first);
    11. // same for the text.
    12. }
    To copy to clipboard, switch view to plain text mode 

    That's just a quick mockup but I guess you see where it is going. This way you don't need a function calculating each bounding rect.

  14. The following user says thank you to Lykurg for this useful post:

    Adam Badura (20th February 2013)

  15. #13
    Join Date
    Aug 2012
    Location
    Wrocław, Poland
    Posts
    25
    Thanks
    3
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: How to simplify a complex item delegate?

    Quote Originally Posted by Lykurg View Post
    This way you don't need a function calculating each bounding rect.
    (Just a quick note, I will think about both above solutions a bit more later.)

    I need to know the size for QStyledItemDelegate::sizeHint as well...

    Also I considered using columns. At least to separate the thumbnail and labels issues. But I found it to complex and risky in face of the two modes I described earlier. And thus I considered making those two separate QTreeView in the first place. I will think about it as well.

  16. #14
    Join Date
    Jan 2006
    Location
    Germany
    Posts
    4,380
    Thanks
    19
    Thanked 1,005 Times in 913 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows Symbian S60
    Wiki edits
    5

    Default Re: How to simplify a complex item delegate?

    Quote Originally Posted by Adam Badura View Post
    I need to know the size for QStyledItemDelegate::sizeHint as well...
    Yes, but only the height and width, not every exact position of the elements. Also I guess the count of labels is known and static, so you can cache that information. So it would be easy:
    Qt Code:
    1. int countOfLabels = 3; // or whatever
    2. int h = 0;
    3. h = countOfLabels * (fontmetrics.height() + padding)
    4. h = qMax(h, heightOfThumbnail);
    To copy to clipboard, switch view to plain text mode 

    Also I considered using columns.
    Also that doesn't change much of my example:
    Qt Code:
    1. QList<QPair<QString,QString> > labels; // a pair has "label:value"
    2. // Draw the pixmap
    3. int currentX = pixmap.width() + padding /* +... */;
    4.  
    5. // then drawing
    6. int height = fontmetrics.height() + padding;
    7. for(int i = /*...*/) {
    8. painter->drawText(QRect(currentX, i*height, maxDescWidth, height), Qt::AlignRight, labels.at(i).first);
    9. // same for the text.
    10. }
    To copy to clipboard, switch view to plain text mode 

    The solution with a QWidget is possible but then you could simply use Q***Widget. And also the delegate functions are called quite a lot so it isn't with good performance.

  17. #15
    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: How to simplify a complex item delegate?

    Quote Originally Posted by Adam Badura View Post
    Over 10 days passed. You were here. And yet you did not provide those trivial 3-6 lines...
    Ouch, sorry, I forgot about it.

    This should work (not tested but you should get the picture...)

    Qt Code:
    1. void paint ( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const {
    2. QPixmap px = index.data(Qt::DecorationRole).toPixmap();
    3. painter->drawPixmap(option.rect.topLeft()+QPoint(1,1), px);
    4. painter->drawText(option.rect.adjusted(px.width+1+5, 1, -1, -1), Qt::AlighLeft|Qt::AlignTop, QString("%1\n%2\n%3").arg(index.data(Qt::DisplayRole).toString()).arg(index.data(...).toString()).arg(index.data(...).toString()));
    5. }
    To copy to clipboard, switch view to plain text mode 

    Similar for sizeHint(), just use QFontMetrics::boundingRect() instead of painting.

    Edit: Next time, instead of assuming my bad will, just send me a PM with a reminder or bump the thread.
    Last edited by wysota; 20th February 2013 at 12:02.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  18. #16
    Join Date
    Aug 2012
    Location
    Wrocław, Poland
    Posts
    25
    Thanks
    3
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: How to simplify a complex item delegate?

    Quote Originally Posted by wysota View Post
    This should work (not tested but you should get the picture...)

    Qt Code:
    1. void paint ( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const {
    2. QPixmap px = index.data(Qt::DecorationRole).toPixmap();
    3. painter->drawPixmap(option.rect.topLeft()+QPoint(1,1), px);
    4. painter->drawText(option.rect.adjusted(px.width+1+5, 1, -1, -1), Qt::AlighLeft|Qt::AlignTop, QString("%1\n%2\n%3").arg(index.data(Qt::DisplayRole).toString()).arg(index.data(...).toString()).arg(index.data(...).toString()));
    5. }
    To copy to clipboard, switch view to plain text mode 
    Only that this does not do what I wanted. The 3 text fields consist of two columns which have to be aligned properly. I did mention that and it was visible on the image of current state I posted in the mean time.

    Although I do like the idea of drawing multiline text. I wasn't aware this is possible. Some simplification at least.

    Quote Originally Posted by Lykurg View Post
    The solution with a QWidget is possible but then you could simply use Q***Widget. And also the delegate functions are called quite a lot so it isn't with good performance.
    Why do you think this is bad? I am actually very attracted to this idea as it would allow me to do what I indeed wanted: use UI for designing the items. Also this might ease styling. After all the QWidget drawing/layout would do the same thing that I would do "by hand".

  19. #17
    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: How to simplify a complex item delegate?

    Quote Originally Posted by Adam Badura View Post
    Only that this does not do what I wanted. The 3 text fields consist of two columns which have to be aligned properly. I did mention that and it was visible on the image of current state I posted in the mean time.
    I don't see any "two columns" on the image you posted (http://stackoverflow.com/questions/4...tyled-listview). Could you elaborate what you mean? I can see a thumbnail and four rows of single word strings.

    Why do you think this is bad?
    This is really bad, trust me Try having more than 10 rows with cell widgets and notice how performance drops. If you need anything complex I would really consider using QtQuick for the view.

    Anyway I will think about some mechanism for simplified delegate layout. I think for static cases such as yours this is possible. It's much more complicated if you want to do animations (e.g. like in QProgressBar on modern Windows). I used to tutor a bachelor thesis that aimed to work around this problem.

    If you don't hear back from me in a couple of days, send me a PM or bump the thread.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  20. #18
    Join Date
    Aug 2012
    Location
    Wrocław, Poland
    Posts
    25
    Thanks
    3
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: How to simplify a complex item delegate?

    Quote Originally Posted by wysota View Post
    I don't see any "two columns" on the image you posted (http://stackoverflow.com/questions/4...tyled-listview). Could you elaborate what you mean? I can see a thumbnail and four rows of single word strings.
    See second paragraph of my first post. Then second paragraph of the post in which I asked you for sample. Then the post in which I provided my current code and a snapshot of what it does. The Windows Media Player example was just that. An example of similar layout which I found quickly. I didn't know any better example and didn't want to spend to much time looking for one.


    Quote Originally Posted by wysota View Post
    This is really bad, trust me Try having more than 10 rows with cell widgets and notice how performance drops. If you need anything complex I would really consider using QtQuick for the view.
    I didn't want to have QWidget for every item. (This way I could use QTreeWidget instead...) I wanted to have just one object hidden behind the scenes which I would feed with data (either directly or by sharing model and changing "active index") to than size/paint through it. Would that be bad to? Why? What more would it do (as compared to ordinary delegate) that it would influence performance so much?

    I cannot switch to QtQuick. I would like but the decision is not up to me.

  21. #19
    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: How to simplify a complex item delegate?

    Quote Originally Posted by Adam Badura View Post
    See second paragraph of my first post. Then second paragraph of the post in which I asked you for sample. Then the post in which I provided my current code and a snapshot of what it does. The Windows Media Player example was just that. An example of similar layout which I found quickly. I didn't know any better example and didn't want to spend to much time looking for one.
    Your delegate is still pretty simple.

    I didn't want to have QWidget for every item. (This way I could use QTreeWidget instead...)
    I don't understand how using QTreeWidget influences anything here.

    I wanted to have just one object hidden behind the scenes which I would feed with data (either directly or by sharing model and changing "active index") to than size/paint through it. Would that be bad to? Why?
    You would have to modify most properties of that object during every paint which is quite heavy.

    I cannot switch to QtQuick.
    Not even for this single view?
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  22. #20
    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: How to simplify a complex item delegate?

    Just to let you know, I already have a preliminary working solution. It's not pixel-perfect yet, but it already gives acceptable results.

    delegatelayout.jpg

    Qt Code:
    1. DelegateLayout *l = new DelegateLayoutFrame(Qt::Horizontal);
    2. l->setSpacing(10);
    3. l->setMargins(QMargins(5,5,5,5));
    4. DelegatePixmap *p1 = new DelegatePixmap(l);
    5. DelegateText *t1 = new DelegateText(l);
    6. t1->setRole(Qt::UserRole+1);
    7. t1->setMargins(QMargins(5,5,5,5));
    8. t1->setMinimumSize(QSize(QFontMetrics(f).width("MMMM"), 1));
    9.  
    10. DelegateLayout *headersl = new DelegateLayout(Qt::Vertical, l);
    11. DelegateStaticText *h1 = new DelegateStaticText(headersl);
    12. h1->setText("Name:");
    13. DelegateStaticText *h2 = new DelegateStaticText(headersl);
    14. h2->setText("Created:");
    15.  
    16. DelegateLayout *valuesl = new DelegateLayout(Qt::Vertical, l);
    17. DelegateText *t2 = new DelegateText(valuesl);
    18. t2->setRole(Qt::DisplayRole);
    19. t2->setForegroundColor(Qt::darkGreen);
    20. DelegateText *t3 = new DelegateText(valuesl);
    21. t3->setRole(Qt::UserRole);
    22.  
    23. LayoutDelegate *ld = new LayoutDelegate(&v);
    24. ld->setLayout(l);
    25. v.setItemDelegate(ld);
    26. v.setModel(&model);
    27.  
    28. v.show();
    To copy to clipboard, switch view to plain text mode 
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


Similar Threads

  1. QLabel as an item delegate
    By qlands in forum Qt Programming
    Replies: 13
    Last Post: 12th August 2011, 11:51
  2. Using model indices in complex model item relationships
    By hackerNovitiate in forum Newbie
    Replies: 0
    Last Post: 29th June 2011, 14:30
  3. Replies: 0
    Last Post: 10th March 2011, 11:44
  4. Replies: 5
    Last Post: 10th August 2009, 10:50
  5. Delegate for a certain item?
    By somebody in forum Qt Programming
    Replies: 1
    Last Post: 18th August 2008, 22:55

Tags for this Thread

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.