2 Attachment(s)
QTreeWidgetItem - widget with layout collapsing
Hello! I have troubles with creating userlist in my IM. Because I need to display some data in one Item. I decided to embed QFrame into widget, make layout and insert labels into that layout. Here is code of my function used to create item (pointer is returned, needed by userlist manager)
Code:
QTlenPresence type,
{
hLayout->setAlignment(Qt::AlignTop);
vLayout->setAlignment(Qt::AlignTop);
statusIcon->setFixedSize(16,16);
switch (type)
{
case Online:
statusIcon
->setPixmap
(QPixmap(QString::fromUtf8(":/icons/icons/16x16/online.png")));
break;
case Chatty:
statusIcon
->setPixmap
(QPixmap(QString::fromUtf8(":/icons/icons/16x16/chatty.png")));
break;
case Away:
statusIcon
->setPixmap
(QPixmap(QString::fromUtf8(":/icons/icons/16x16/away.png")));
break;
case XA:
statusIcon
->setPixmap
(QPixmap(QString::fromUtf8(":/icons/icons/16x16/xa.png")));
break;
case DND:
statusIcon
->setPixmap
(QPixmap(QString::fromUtf8(":/icons/icons/16x16/dnd.png")));
break;
case Offline:
statusIcon
->setPixmap
(QPixmap(QString::fromUtf8(":/icons/icons/16x16/offline.png")));
break;
}
hLayout->addWidget(statusIcon);
hLayout->addLayout(vLayout);
nameFont.setBold(true);
nameLabel->setFont(nameFont);
vLayout->addWidget(nameLabel);
if (!desc.isEmpty() && settings->value("/roster/show_descriptions", false).toBool())
{
descFont.setPointSize(7);
descFont.setItalic(true);
descLabel->setWordWrap(true);
descLabel->setFont(descFont);
vLayout->addWidget(descLabel);
}
//prowizorka
if(settings->value("/roster/show_avatars", false).toBool())
{
if(pxAvatar.isNull())
avatar
->setPixmap
(QPixmap(QString::fromUtf8(":/icons/icons/64x64/default_av.png")));
else
avatar->setPixmap(pxAvatar);
avatar->setAlignment(Qt::AlignRight);
hLayout->addWidget(avatar);
}
frame->setLayout(hLayout);
setItemWidget(item, 0, frame);
return item;
}
and here is roster with only one item visible and with two visible; height is calculated properly, but layout is collapsed.
how to fix that in best way?
thanks in advance.
Re: QTreeWidgetItem - widget with layout collapsing
The best way is not to embed widgets but use delegates or at least report a proper size hint from the items.
And please don't link images from 3-rd party sites, they tend to vanish over time making the thread useless. Attach images to your post instead.
Re: QTreeWidgetItem - widget with layout collapsing
so I should try with QTreeView and QItemDelegate? I wanted to avoid that.
Images are located on my server, so wont disappear without my knowledge ;)
Re: QTreeWidgetItem - widget with layout collapsing
Quote:
Originally Posted by
enkidu
so I should try with QTreeView and QItemDelegate? I wanted to avoid that.
You can keep using QTreeWidget but you should implement your own item delegate.
Quote:
Images are located on my server, so wont disappear without my knowledge ;)
But they will disappear without my knowledge. I don't care if you remove them willingly or not, it's a fact that if they disappear, others won't benefit from this thread.
Re: QTreeWidgetItem - widget with layout collapsing
After making some other task I decided to reimplement item delegate. I modified StarDelegate example and finally got this:
qtlenrosteritemdelegate.hpp
Code:
#ifndef QTLENROSTERITEMDELEGATE_HPP
#define QTLENROSTERITEMDELEGATE_HPP
#include <QtGui>
#include "qtlenrosteritem.hpp"
class QTlenRosterItemDelegate: public QStyledItemDelegate
{
Q_OBJECT
public:
QTlenRosterItemDelegate
(QWidget *parent
= 0) : QStyledItemDelegate
(parent
) {}
};
#endif // QTLENROSTERITEMDELEGATE_HPP
qtlenrosteritemdelegate.cpp
Code:
{
if (qVariantCanConvert<QTlenRosterItem>(index.data())) {
QTlenRosterItem rosterItem = qVariantValue<QTlenRosterItem>(index.data());
bool checked = false;
if (option.
state & QStyle::State_Selected) {
painter->fillRect(option.rect, option.palette.highlight());
checked = true;
}
rosterItem.setHeight(rosterItem.paint(painter, option.rect, option.palette, checked));
} else {
QStyledItemDelegate::paint(painter, option, index);
}
}
{
if (qVariantCanConvert<QTlenRosterItem>(index.data())) {
QTlenRosterItem rosterItem = qVariantValue<QTlenRosterItem>(index.data());
return rosterItem.sizeHint(option);
} else {
return QStyledItemDelegate::sizeHint(option, index);
}
}
qtlenrosteritem.hpp
Code:
#ifndef QTLENROSTERITEM_HPP
#define QTLENROSTERITEM_HPP
#include "defines.h"
#include <QtGui>
class QTlenRosterItem
{
public:
const QPalette &palette,
bool checked
) const;
int height;
void setHeight(int);
private:
};
Q_DECLARE_METATYPE(QTlenRosterItem)
#endif // QTLENROSTERITEM_HPP
qtlenrosteritem.cpp
Code:
#include "qtlenrosteritem.hpp"
{
this->name = name;
this->desc = desc;
this->jid = jid;
this->avatar = pxAvatar;
height = 68;
switch (type)
{
case Online:
presence
=QPixmap(QString::fromUtf8(":/icons/icons/16x16/online.png"));
break;
case Chatty:
presence
=QPixmap(QString::fromUtf8(":/icons/icons/16x16/chatty.png"));
break;
case Away:
break;
case XA:
break;
case DND:
break;
case Offline:
presence
=QPixmap(QString::fromUtf8(":/icons/icons/16x16/offline.png"));
break;
}
}
int QTlenRosterItem
::paint(QPainter *painter,
const QRect &rect,
const QPalette &palette,
bool checked
) const {
painter->save();
painter
->setRenderHint
(QPainter::Antialiasing,
true);
if (checked) painter->setBrush(palette.highlightedText());
else
painter->setBrush(palette.foreground());
//name
nameRect.setLeft(rect.left()+20);
nameRect.setRight(rect.right()-68);
nameRect.setTop(rect.top()+2);
nameRect.setBottom(rect.bottom()-2);
nameFont.setBold(true);
painter->setFont(nameFont);
painter->drawText(nameRect, (int)(Qt::AlignLeft | Qt::TextWordWrap), name, nameBR);
//jid
jidRect.setLeft(rect.left()+20);
jidRect.setRight(rect.right()-68);
jidRect.setTop(nameBR->bottom()+2);
jidRect.setBottom(nameBR->bottom()+18);
nameFont.setBold(false);
painter->setFont(nameFont);
painter->drawText(jidRect, (int)(Qt::AlignLeft | Qt::TextWordWrap), jid, jidBR);
//desc
descRect.setLeft(rect.left()+20);
descRect.setRight(rect.right()-68);
descRect.setTop(jidBR->bottom()+2);
descRect.setBottom(rect.bottom()-2);
descFont.setPointSize(7);
descFont.setItalic(true);
painter->setFont(descFont);
painter->drawText(descRect, (int)(Qt::AlignLeft | Qt::TextWordWrap), desc, descBR);
int textHeight = nameBR->height() + jidBR->height() + descBR->height()+8;
int theight;
if (textHeight > 68)
theight = textHeight;
else
theight = 68;
//setHeight(68);
painter->drawPixmap(rect.left()+2, rect.top()-8+rect.height()/2,16, 16, presence);
painter->drawPixmap(rect.right()-66, rect.top()+2, 64, 64, avatar);
painter->restore();
return theight;
}
{
descFont.setPointSize(7);
descFont.setItalic(true);
QRect rect
= fm.
boundingRect(0,
0,
80,
160,
(int)(Qt
::AlignLeft | Qt
::TextWordWrap), desc
);
int h = rect.height();
if ((h + 30) < 68)
}
void QTlenRosterItem::setHeight(int h)
{
height = h;
}
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.