You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

180 lines
7.4 KiB

#include "channeldelegate.h"
#include <QPainter>
#include <QApplication>
ChannelDelegate::ChannelDelegate(QObject *parent)
: QStyledItemDelegate(parent) {}
QRect ChannelDelegate::inviteButtonRect(const QRect &itemRect) {
const int margin = 6;
return QRect(itemRect.right() - margin - InviteBtnSize,
itemRect.bottom() - margin - InviteBtnSize,
InviteBtnSize, InviteBtnSize);
}
void ChannelDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
const QModelIndex &index) const {
painter->save();
const int barWidth = 4;
const int margin = 8;
const int iconSize = 32;
int peersOnline = index.data(ChannelPeersOnlineRole).toInt();
int autoActive = index.data(ChannelAutoConnectActiveRole).toInt();
/* ── background ── */
if (option.state & QStyle::State_Selected) {
painter->fillRect(option.rect, option.palette.highlight());
} else if (option.state & QStyle::State_MouseOver) {
painter->fillRect(option.rect, option.palette.light());
} else {
painter->fillRect(option.rect, option.palette.base());
}
/* ── vertical status bar (left edge, over background) ── */
QColor barColor = Qt::transparent;
if (peersOnline > 0) barColor = QColor("#4CAF50");
else if (autoActive && peersOnline == 0) barColor = QColor("#FFC107");
if (barColor.alpha() > 0) {
QRect barRect(option.rect.left(), option.rect.top(), barWidth, option.rect.height());
painter->fillRect(barRect, barColor);
}
QRect iconRect(option.rect.left() + margin + barWidth,
option.rect.top() + (option.rect.height() - iconSize) / 2,
iconSize, iconSize);
QIcon icon = qvariant_cast<QIcon>(index.data(ChannelIconRole));
if (!icon.isNull()) {
icon.paint(painter, iconRect);
}
/* ── online count badge (top-left of avatar, above it) ── */
if (peersOnline > 0) {
int badgeSize = 16;
QRect badgeRect(iconRect.left() - 4, iconRect.top() - 6, badgeSize, badgeSize);
painter->setRenderHint(QPainter::Antialiasing);
painter->setBrush(QColor("#4CAF50"));
painter->setPen(QPen(Qt::white, 1.5));
painter->drawEllipse(badgeRect);
QFont badgeFont = option.font;
badgeFont.setBold(true);
badgeFont.setPixelSize(10);
painter->setFont(badgeFont);
painter->setPen(Qt::white);
QString num = QString::number(peersOnline);
if (peersOnline > 9) num = "9+";
painter->drawText(badgeRect, Qt::AlignCenter, num);
}
QRect textRect(iconRect.right() + margin, option.rect.top() + margin,
option.rect.right() - iconRect.right() - 2 * margin,
option.rect.height() - 2 * margin);
QString name = index.data(ChannelNameRole).toString();
QFont nameFont = option.font;
nameFont.setBold(true);
nameFont.setPointSize(nameFont.pointSize() + 1);
painter->setFont(nameFont);
QColor textColor = (option.state & QStyle::State_Selected)
? option.palette.highlightedText().color()
: option.palette.text().color();
painter->setPen(textColor);
QRect nameRect = textRect;
nameRect.setHeight(QFontMetrics(nameFont).height());
painter->drawText(nameRect, Qt::AlignLeft | Qt::AlignTop,
painter->fontMetrics().elidedText(name, Qt::ElideRight, nameRect.width()));
QString lastMsg = index.data(ChannelLastMessageRole).toString();
if (!lastMsg.isEmpty()) {
QFont msgFont = option.font;
msgFont.setPointSize(msgFont.pointSize() - 1);
QColor nickColor(0x33, 0x90, 0xEC);
QColor msgColor = (option.state & QStyle::State_Selected)
? option.palette.highlightedText().color().darker(120)
: QColor(128, 128, 128);
if (option.state & QStyle::State_Selected) nickColor = nickColor.lighter(140);
QRect msgRect(textRect.left(), nameRect.bottom() + 4,
textRect.right() - InviteBtnSize - 6 - textRect.left(),
option.rect.bottom() - nameRect.bottom() - margin);
QFontMetrics msgFm(msgFont);
int colon = lastMsg.indexOf(QString::fromUtf8(": "));
if (colon >= 0) {
QString nick = lastMsg.left(colon + 1);
QString body = lastMsg.mid(colon + 2);
painter->setFont(msgFont);
painter->setPen(nickColor);
QRect nickRect = msgRect;
nickRect.setWidth(msgFm.horizontalAdvance(nick));
painter->drawText(nickRect, Qt::AlignLeft | Qt::AlignTop, nick);
painter->setPen(msgColor);
QRect bodyRect(msgRect.left() + nickRect.width(), msgRect.top(),
msgRect.width() - nickRect.width(), msgRect.height());
QString elidedBody = msgFm.elidedText(body, Qt::ElideRight, bodyRect.width());
painter->drawText(bodyRect, Qt::AlignLeft | Qt::AlignTop | Qt::TextWordWrap, elidedBody);
} else {
painter->setFont(msgFont);
painter->setPen(msgColor);
QString elided = msgFm.elidedText(lastMsg, Qt::ElideRight, msgRect.width());
painter->drawText(msgRect, Qt::AlignLeft | Qt::AlignTop | Qt::TextWordWrap, elided);
}
}
/* ── unread count badge (right of channel name) ── */
int unread = index.data(ChannelUnreadCountRole).toInt();
if (unread > 0) {
QString unreadText = unread > 99 ? QStringLiteral("99+") : QString::number(unread);
QFont badgeFont = option.font;
badgeFont.setBold(true);
badgeFont.setPixelSize(11);
QFontMetrics badgeFm(badgeFont);
int textW = badgeFm.horizontalAdvance(unreadText) + 8;
int badgeH = 18;
if (textW < badgeH) textW = badgeH;
QRect badgeRect(textRect.right() - textW, nameRect.top(),
textW, badgeH);
painter->setRenderHint(QPainter::Antialiasing);
painter->setBrush(QColor("#E53935"));
painter->setPen(Qt::NoPen);
painter->drawRoundedRect(badgeRect, badgeH / 2, badgeH / 2);
painter->setFont(badgeFont);
painter->setPen(Qt::white);
painter->drawText(badgeRect, Qt::AlignCenter, unreadText);
}
/* ── invite plus button (bottom-right) ── */
QRect plusRect = inviteButtonRect(option.rect);
bool plusHovered = index.data(ChannelInviteBtnHoveredRole).toInt() != 0;
painter->setRenderHint(QPainter::Antialiasing);
if (plusHovered) {
painter->setBrush(QColor(0x33, 0x90, 0xEC));
painter->setPen(Qt::NoPen);
painter->drawEllipse(plusRect);
painter->setPen(QPen(Qt::white, 2));
} else {
painter->setBrush(QColor(0x33, 0x90, 0xEC, 110));
painter->setPen(Qt::NoPen);
painter->drawEllipse(plusRect);
painter->setPen(QPen(QColor(0x33, 0x90, 0xEC), 2));
}
painter->drawLine(plusRect.center().x(), plusRect.top() + 5,
plusRect.center().x(), plusRect.bottom() - 5);
painter->drawLine(plusRect.left() + 5, plusRect.center().y(),
plusRect.right() - 5, plusRect.center().y());
painter->restore();
}
QSize ChannelDelegate::sizeHint(const QStyleOptionViewItem &option,
const QModelIndex &index) const {
Q_UNUSED(option);
Q_UNUSED(index);
return QSize(200, 56);
}