#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.top() + margin, InviteBtnSize, InviteBtnSize); } QRect ChannelDelegate::inviteByLinkButtonRect(const QRect &itemRect) { const int margin = 6; return QRect(itemRect.right() - margin - InviteBtnSize * 2 - InviteBtnGap, itemRect.top() + margin, InviteBtnSize, InviteBtnSize); } QRect ChannelDelegate::settingsButtonRect(const QRect &itemRect) { const int margin = 6; return QRect(itemRect.right() - margin - InviteBtnSize * 3 - InviteBtnGap * 2, itemRect.top() + margin, InviteBtnSize, InviteBtnSize); } void ChannelDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { painter->save(); /* ── заголовок секции (например, «Личные») ── */ if (index.data(ChannelIsSectionRole).toBool()) { painter->fillRect(option.rect, option.palette.window()); painter->setPen(option.palette.mid().color()); QFont f = option.font; f.setBold(true); painter->setFont(f); QRect tr = option.rect.adjusted(12, 0, -8, 0); painter->drawText(tr, Qt::AlignLeft | Qt::AlignVCenter, index.data(ChannelNameRole).toString()); painter->restore(); return; } 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()); nameRect.setRight(nameRect.right() - InviteBtnSize * 3 - InviteBtnGap * 2 - 4); 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.width(), 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 (top-right) ── */ QRect plusRect = inviteButtonRect(option.rect); bool plusHovered = index.data(ChannelInviteBtnHoveredRole).toInt() != 0; painter->setRenderHint(QPainter::Antialiasing); QColor plusFill = plusHovered ? QColor(0x4A, 0xA4, 0xF0) : QColor(0x33, 0x90, 0xEC); painter->setBrush(plusFill); painter->setPen(Qt::NoPen); painter->drawEllipse(plusRect); painter->setPen(QPen(Qt::white, 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()); /* ── invite-by-link button (left of plus, orange square with arrow) ── */ QRect invRect = inviteByLinkButtonRect(option.rect); bool invHovered = index.data(ChannelInviteByLinkBtnHoveredRole).toInt() != 0; painter->setRenderHint(QPainter::Antialiasing); QColor invFill = invHovered ? QColor(0xF0, 0x90, 0x30) : QColor(0xE6, 0x7E, 0x22); painter->setBrush(invFill); painter->setPen(Qt::NoPen); painter->drawRoundedRect(invRect, 3, 3); painter->setPen(QPen(Qt::white, 1.5)); /* arrow: ← */ int cx = invRect.center().x(), cy = invRect.center().y(); int dx = 3; painter->drawLine(cx + dx, cy - 3, cx - dx, cy); painter->drawLine(cx + dx, cy + 3, cx - dx, cy); painter->drawLine(cx + dx + 1, cy, cx + dx + 1, cy - 3 + 1); painter->drawLine(cx + dx + 1, cy, cx + dx + 1, cy + 3 - 1); /* ── settings gear (left of invite-by-link button) ── */ QRect gearRect = settingsButtonRect(option.rect); bool gearHovered = index.data(ChannelSettingsBtnHoveredRole).toInt() != 0; QColor gearColor = gearHovered ? QColor("#3390EC") : QColor("#555"); painter->setPen(QPen(gearColor, 2)); painter->setBrush(Qt::NoBrush); int gr = 5; painter->drawEllipse(gearRect.center(), gr, gr); painter->drawEllipse(gearRect.center(), gr / 2, gr / 2); int gcx = gearRect.center().x(), gcy = gearRect.center().y(); painter->drawLine(gcx, gcy - gr, gcx, gcy - gr + 1); painter->drawLine(gcx, gcy + gr, gcx, gcy + gr - 1); painter->drawLine(gcx - gr, gcy, gcx - gr + 1, gcy); painter->drawLine(gcx + gr, gcy, gcx + gr - 1, gcy); painter->drawLine(gcx - 3, gcy - 4, gcx - 3, gcy - 5); painter->drawLine(gcx + 3, gcy + 4, gcx + 3, gcy + 5); painter->drawLine(gcx - 4, gcy - 3, gcx - 5, gcy - 3); painter->drawLine(gcx + 4, gcy + 3, gcx + 5, gcy + 3); painter->restore(); } QSize ChannelDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const { Q_UNUSED(option); Q_UNUSED(index); return QSize(200, 56); }