166 lines
7.0 KiB
C++
166 lines
7.0 KiB
C++
#include "channeldelegate.h"
|
|
#include <QPainter>
|
|
#include <QApplication>
|
|
|
|
ChannelDelegate::ChannelDelegate(QObject *parent)
|
|
: QStyledItemDelegate(parent) {}
|
|
|
|
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;
|
|
|
|
bool isDm = index.data(ChannelChannelIdRole).toString().startsWith(QStringLiteral("dm:"));
|
|
bool dmOnline = index.data(ChannelDmOnlineRole).toBool();
|
|
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 (isDm || peersOnline > 0) {
|
|
int badgeSize = 16;
|
|
QRect badgeRect(iconRect.left() - 4, iconRect.top() - 6, badgeSize, badgeSize);
|
|
painter->setRenderHint(QPainter::Antialiasing);
|
|
painter->setBrush(QColor(isDm && !dmOnline ? "#E53935" : "#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+";
|
|
if (!isDm) 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());
|
|
int unread = index.data(ChannelUnreadCountRole).toInt();
|
|
QString unreadText = unread > 99 ? QStringLiteral("99+") : QString::number(unread);
|
|
QFont unreadFont = option.font; unreadFont.setBold(true); unreadFont.setPixelSize(11);
|
|
int unreadWidth = qMax(18, QFontMetrics(unreadFont).horizontalAdvance(unreadText) + 8);
|
|
if (unread > 0) nameRect.setRight(nameRect.right() - unreadWidth - 6);
|
|
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) ── */
|
|
if (unread > 0) {
|
|
int badgeH = 18;
|
|
QRect badgeRect(textRect.right() - unreadWidth, nameRect.top(), unreadWidth, badgeH);
|
|
painter->setRenderHint(QPainter::Antialiasing);
|
|
painter->setBrush(QColor("#E53935"));
|
|
painter->setPen(Qt::NoPen);
|
|
painter->drawRoundedRect(badgeRect, badgeH / 2, badgeH / 2);
|
|
painter->setFont(unreadFont);
|
|
painter->setPen(Qt::white);
|
|
painter->drawText(badgeRect, Qt::AlignCenter, unreadText);
|
|
}
|
|
|
|
painter->restore();
|
|
}
|
|
|
|
QSize ChannelDelegate::sizeHint(const QStyleOptionViewItem &option,
|
|
const QModelIndex &index) const {
|
|
Q_UNUSED(option);
|
|
Q_UNUSED(index);
|
|
return QSize(200, 56);
|
|
}
|