After making some other task I decided to reimplement item delegate. I modified StarDelegate example and finally got this:
qtlenrosteritemdelegate.hpp
Qt Code:
  1. #ifndef QTLENROSTERITEMDELEGATE_HPP
  2. #define QTLENROSTERITEMDELEGATE_HPP
  3. #include <QtGui>
  4. #include "qtlenrosteritem.hpp"
  5. class QTlenRosterItemDelegate: public QStyledItemDelegate
  6. {
  7. Q_OBJECT
  8. public:
  9. QTlenRosterItemDelegate(QWidget *parent = 0) : QStyledItemDelegate(parent) {}
  10. void paint(QPainter *painter, const QStyleOptionViewItem &option,
  11. const QModelIndex &index) const;
  12. QSize sizeHint(const QStyleOptionViewItem &option,
  13. const QModelIndex &index) const;
  14.  
  15. };
  16.  
  17. #endif // QTLENROSTERITEMDELEGATE_HPP
To copy to clipboard, switch view to plain text mode 
qtlenrosteritemdelegate.cpp
Qt Code:
  1. void QTlenRosterItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
  2. const QModelIndex &index) const
  3. {
  4. if (qVariantCanConvert<QTlenRosterItem>(index.data())) {
  5. QTlenRosterItem rosterItem = qVariantValue<QTlenRosterItem>(index.data());
  6. bool checked = false;
  7. if (option.state & QStyle::State_Selected)
  8. {
  9. painter->fillRect(option.rect, option.palette.highlight());
  10. checked = true;
  11. }
  12. rosterItem.setHeight(rosterItem.paint(painter, option.rect, option.palette, checked));
  13. } else {
  14. QStyledItemDelegate::paint(painter, option, index);
  15. }
  16. }
  17.  
  18. QSize QTlenRosterItemDelegate::sizeHint(const QStyleOptionViewItem &option,
  19. const QModelIndex &index) const
  20. {
  21. if (qVariantCanConvert<QTlenRosterItem>(index.data())) {
  22.  
  23. QTlenRosterItem rosterItem = qVariantValue<QTlenRosterItem>(index.data());
  24. return rosterItem.sizeHint(option);
  25. } else {
  26. return QStyledItemDelegate::sizeHint(option, index);
  27. }
  28. }
To copy to clipboard, switch view to plain text mode 
qtlenrosteritem.hpp
Qt Code:
  1. #ifndef QTLENROSTERITEM_HPP
  2. #define QTLENROSTERITEM_HPP
  3. #include "defines.h"
  4. #include <QtGui>
  5. class QTlenRosterItem
  6. {
  7. public:
  8. QTlenRosterItem(QString name = "", QTlenPresence type = Offline, QString desc="", QString jid="", QPixmap pxAvatar=QPixmap());
  9. int paint(QPainter *painter, const QRect &rect,
  10. const QPalette &palette, bool checked) const;
  11. QSize sizeHint(const QStyleOptionViewItem &option) const;
  12. int height;
  13. void setHeight(int);
  14. private:
  15. QString name;
  16. QPixmap presence;
  17. QString desc;
  18. QString jid;
  19. QPixmap avatar;
  20. };
  21. Q_DECLARE_METATYPE(QTlenRosterItem)
  22. #endif // QTLENROSTERITEM_HPP
To copy to clipboard, switch view to plain text mode 
qtlenrosteritem.cpp
Qt Code:
  1. #include "qtlenrosteritem.hpp"
  2.  
  3. QTlenRosterItem::QTlenRosterItem(QString name, QTlenPresence type, QString desc, QString jid, QPixmap pxAvatar)
  4. {
  5. this->name = name;
  6. this->desc = desc;
  7. this->jid = jid;
  8. this->avatar = pxAvatar;
  9. height = 68;
  10. switch (type)
  11. {
  12. case Online:
  13. presence=QPixmap(QString::fromUtf8(":/icons/icons/16x16/online.png"));
  14. break;
  15. case Chatty:
  16. presence=QPixmap(QString::fromUtf8(":/icons/icons/16x16/chatty.png"));
  17. break;
  18. case Away:
  19. presence=QPixmap(QString::fromUtf8(":/icons/icons/16x16/away.png"));
  20. break;
  21. case XA:
  22. presence=QPixmap(QString::fromUtf8(":/icons/icons/16x16/xa.png"));
  23. break;
  24. case DND:
  25. presence=QPixmap(QString::fromUtf8(":/icons/icons/16x16/dnd.png"));
  26. break;
  27. case Offline:
  28. presence=QPixmap(QString::fromUtf8(":/icons/icons/16x16/offline.png"));
  29. break;
  30. }
  31. }
  32.  
  33. int QTlenRosterItem::paint(QPainter *painter, const QRect &rect, const QPalette &palette, bool checked) const
  34. {
  35. painter->save();
  36. painter->setRenderHint(QPainter::Antialiasing, true);
  37. if (checked) painter->setBrush(palette.highlightedText());
  38. else
  39. painter->setBrush(palette.foreground());
  40. //name
  41. QRect nameRect;
  42. nameRect.setLeft(rect.left()+20);
  43. nameRect.setRight(rect.right()-68);
  44. nameRect.setTop(rect.top()+2);
  45. nameRect.setBottom(rect.bottom()-2);
  46. QRect *nameBR = new QRect;
  47. QFont nameFont;
  48. nameFont.setBold(true);
  49. painter->setFont(nameFont);
  50. painter->drawText(nameRect, (int)(Qt::AlignLeft | Qt::TextWordWrap), name, nameBR);
  51. //jid
  52. QRect jidRect;
  53. jidRect.setLeft(rect.left()+20);
  54. jidRect.setRight(rect.right()-68);
  55. jidRect.setTop(nameBR->bottom()+2);
  56. jidRect.setBottom(nameBR->bottom()+18);
  57. QRect *jidBR = new QRect;
  58. nameFont.setBold(false);
  59. painter->setFont(nameFont);
  60. painter->drawText(jidRect, (int)(Qt::AlignLeft | Qt::TextWordWrap), jid, jidBR);
  61. //desc
  62. QRect descRect;
  63. descRect.setLeft(rect.left()+20);
  64. descRect.setRight(rect.right()-68);
  65. descRect.setTop(jidBR->bottom()+2);
  66. descRect.setBottom(rect.bottom()-2);
  67. QRect *descBR = new QRect;
  68. QFont descFont;
  69. descFont.setPointSize(7);
  70. descFont.setItalic(true);
  71. painter->setFont(descFont);
  72. painter->drawText(descRect, (int)(Qt::AlignLeft | Qt::TextWordWrap), desc, descBR);
  73. int textHeight = nameBR->height() + jidBR->height() + descBR->height()+8;
  74. int theight;
  75. if (textHeight > 68)
  76. theight = textHeight;
  77. else
  78. theight = 68;
  79. //setHeight(68);
  80. painter->drawPixmap(rect.left()+2, rect.top()-8+rect.height()/2,16, 16, presence);
  81. painter->drawPixmap(rect.right()-66, rect.top()+2, 64, 64, avatar);
  82. painter->restore();
  83. return theight;
  84. }
  85.  
  86. QSize QTlenRosterItem::sizeHint(const QStyleOptionViewItem &option) const
  87. {
  88. qDebug(QByteArray::number(option.rect.right()));
  89. QFont descFont;
  90. descFont.setPointSize(7);
  91. descFont.setItalic(true);
  92. QFontMetrics fm(descFont);
  93. QRect rect = fm.boundingRect(0,0,80,160, (int)(Qt::AlignLeft | Qt::TextWordWrap), desc);
  94. int h = rect.height();
  95. if ((h + 30) < 68)
  96. return QSize(160, 68);
  97. return QSize(160, h+30);
  98. }
  99.  
  100. void QTlenRosterItem::setHeight(int h)
  101. {
  102. height = h;
  103. }
To copy to clipboard, switch view to plain text mode 

What I found, that in calculating SizeHint option.rect is not providing width, so I cannot calculate width of text blocks properly. This results in improper calculated height (only few pixels fortunately). Other thing, that is strange for me (maybe I'm misunderstanding docs) is that painter->setBrush(palette.highlightedText()); doesn't work as expected - text is still black (as if I used painter->setBrush(palette.foreground()) while for selected items should be white (or other colour derived from style). Any ideas? Thanks in advance.