#include "channeldelegate.h" #include #include 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(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); }