#include "accountdelegate.h" #include "flagpainter.h" #include "memberlistmodel.h" #include "debug_ui.h" #include #include #include static QRect inviteButtonRect(const QRect& row) { return QRect(row.right() - 31, row.center().y() - 14, 28, 28); } static QRect avatarRect(const QRect& row) { const int size = MemberListModel::kAvatarSize; return QRect(row.left() + 4, row.top() + (row.height() - size) / 2, size, size); } AccountDelegate::AccountDelegate(QObject *parent) : QStyledItemDelegate(parent) { GUI_DEBUG("AccountDelegate: row height=%dpx avatar=%dpx gap=%dpx", MemberListModel::kRowHeight, MemberListModel::kAvatarSize, MemberListModel::kRowHeight - MemberListModel::kAvatarSize); } void AccountDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { painter->save(); 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.alternateBase().color().lighter(115)); else painter->fillRect(option.rect, option.palette.alternateBase()); const int margin = 4; const int iconSz = MemberListModel::kAvatarSize; QIcon icon = qvariant_cast(index.data(Qt::DecorationRole)); if (!icon.isNull()) icon.paint(painter, avatarRect(option.rect)); const int x = option.rect.left() + iconSz + margin * 3; const bool canInvite = !index.data(Qt::UserRole + 2).toBool(); const int w = option.rect.right() - x - margin - (canInvite ? 32 : 0); const int yMid = option.rect.top() + option.rect.height() / 2; uint8_t flags = (uint8_t)(index.data(Qt::UserRole + 3).toInt() & 0xFF); QFont nameFont = painter->font(); nameFont.setBold(true); nameFont.setPixelSize(13); if (flags & MEMBER_FLAG_DELETED) nameFont.setStrikeOut(true); painter->setFont(nameFont); QColor textColor = option.palette.color(QPalette::Text); if (option.state & QStyle::State_Selected) textColor = option.palette.color(QPalette::HighlightedText); if (index.data(Qt::UserRole + 2).toBool()) textColor = QColor("#4CAF50"); painter->setPen(textColor); const uint8_t visualFlags = flags & (MEMBER_FLAG_SUPERNODE | MEMBER_FLAG_ADMIN | MEMBER_FLAG_MODER); int flagX = x; if (visualFlags) { FlagPainter::draw(painter, flags, flagX, option.rect.top() + (option.rect.height() - nameFont.pixelSize()) / 2, nameFont.pixelSize()); int n = __builtin_popcount(visualFlags); flagX += nameFont.pixelSize() * n + (n - 1) * 2; } if (index.data(Qt::UserRole + 4).toBool()) { FlagPainter::drawStorage(painter, flagX, option.rect.top() + (option.rect.height() - nameFont.pixelSize()) / 2, nameFont.pixelSize()); flagX += nameFont.pixelSize() + 2; } if (flags & MEMBER_FLAG_RADIO) { FlagPainter::drawRadio(painter, flagX, option.rect.top() + (option.rect.height() - nameFont.pixelSize()) / 2, nameFont.pixelSize(), textColor); flagX += nameFont.pixelSize() + 2; } QString name = index.data(Qt::DisplayRole).toString(); painter->drawText(QRect(flagX, option.rect.top() + 2, w - (flagX - x), yMid - option.rect.top() - 2), Qt::AlignLeft | Qt::AlignBottom, name); QFont subFont = painter->font(); subFont.setBold(false); subFont.setPixelSize(10); painter->setFont(subFont); painter->setPen(QColor(130, 130, 130)); QString sub = index.data(Qt::UserRole + 1).toString(); if (!sub.isEmpty()) painter->drawText(QRect(flagX, yMid + 2, w - (flagX - x), option.rect.bottom() - yMid - 2), Qt::AlignLeft | Qt::AlignTop, sub); if (canInvite) { QFont plusFont = nameFont; plusFont.setPixelSize(22); plusFont.setStrikeOut(false); painter->setFont(plusFont); painter->setPen(option.palette.color(QPalette::Link)); painter->drawText(inviteButtonRect(option.rect), Qt::AlignCenter, QStringLiteral("+")); } painter->restore(); } bool AccountDelegate::editorEvent(QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index) { Q_UNUSED(model); if (event->type() != QEvent::MouseButtonPress && event->type() != QEvent::MouseButtonRelease && event->type() != QEvent::MouseButtonDblClick) return false; auto* mouse = static_cast(event); if (mouse->button() != Qt::LeftButton) return false; const bool onAvatar = avatarRect(option.rect).contains(mouse->pos()); if (event->type()==QEvent::MouseButtonPress) { m_avatarPress=onAvatar ? index : QModelIndex(); m_avatarPosition=mouse->pos(); } if (onAvatar) { if (event->type()==QEvent::MouseButtonRelease && m_avatarPress==index && (mouse->pos()-m_avatarPosition).manhattanLength()<5) emit avatarRequested(index); if (event->type()==QEvent::MouseButtonRelease) m_avatarPress=QPersistentModelIndex(); return true; } if (index.data(Qt::UserRole + 2).toBool()) return false; const bool inside = inviteButtonRect(option.rect).contains(mouse->pos()); if (event->type() == QEvent::MouseButtonPress) { m_invitePress = inside ? index : QModelIndex(); return inside; } if (event->type() == QEvent::MouseButtonDblClick) return inside; const bool activate = inside && m_invitePress == index; m_invitePress = QPersistentModelIndex(); if (activate) emit inviteRequested(index); return activate; } QSize AccountDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const { (void)option; (void)index; return QSize(160, MemberListModel::kRowHeight); }