Enlarge desktop chat and member avatars

This commit is contained in:
evgeny committed 2026-10-07 01:18:31 +02:00
1 parent 68cb9413db
commit 593aaa42dc
7 files changed
+42 -22

No files matched your search

+14 -5
View File
@@ -1,6 +1,7 @@
#include "accountdelegate.h"
#include "flagpainter.h"
#include "memberlistmodel.h"
#include "debug_ui.h"
#include <QPainter>
#include <QFont>
#include <QMouseEvent>
@@ -9,8 +10,16 @@ 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) {}
: 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 {
@@ -24,11 +33,11 @@ void AccountDelegate::paint(QPainter *painter, const QStyleOptionViewItem &optio
painter->fillRect(option.rect, option.palette.alternateBase());
const int margin = 4;
const int iconSz = 24;
const int iconSz = MemberListModel::kAvatarSize;
QIcon icon = qvariant_cast<QIcon>(index.data(Qt::DecorationRole));
if (!icon.isNull())
icon.paint(painter, option.rect.left() + margin, option.rect.top() + (option.rect.height() - iconSz) / 2, iconSz, iconSz);
icon.paint(painter, avatarRect(option.rect));
const int x = option.rect.left() + iconSz + margin * 3;
const bool canInvite = !index.data(Qt::UserRole + 2).toBool();
@@ -96,7 +105,7 @@ bool AccountDelegate::editorEvent(QEvent* event, QAbstractItemModel* model, cons
event->type() != QEvent::MouseButtonDblClick) return false;
auto* mouse = static_cast<QMouseEvent*>(event);
if (mouse->button() != Qt::LeftButton) return false;
const bool onAvatar=QRect(option.rect.left()+4,option.rect.center().y()-12,24,24).contains(mouse->pos());
const bool onAvatar = avatarRect(option.rect).contains(mouse->pos());
if (event->type()==QEvent::MouseButtonPress) {
m_avatarPress=onAvatar ? index : QModelIndex(); m_avatarPosition=mouse->pos();
}
@@ -119,5 +128,5 @@ bool AccountDelegate::editorEvent(QEvent* event, QAbstractItemModel* model, cons
QSize AccountDelegate::sizeHint(const QStyleOptionViewItem &option,
const QModelIndex &index) const {
(void)option; (void)index;
return QSize(160, 36);
return QSize(160, MemberListModel::kRowHeight);
}
+1 -1
View File
@@ -96,7 +96,7 @@ AccountList::AccountList(DbManager* db, QWidget *parent)
m_listView->setEditTriggers(QAbstractItemView::NoEditTriggers);
m_listView->setSelectionMode(QAbstractItemView::SingleSelection);
m_listView->setMouseTracking(true);
m_listView->setIconSize(QSize(24, 24));
m_listView->setIconSize(QSize(MemberListModel::kAvatarSize, MemberListModel::kAvatarSize));
m_listView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
m_listView->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
m_listView->setContextMenuPolicy(Qt::CustomContextMenu);
+11 -8
View File
@@ -17,12 +17,14 @@ extern "C" {
static void applyPhoto(MemberListItem& item, const QString& channel) {
auto* manager = AvatarManager::instance(); if (!manager) return;
const QImage image = manager->image(channel, item.nodeId); if (image.isNull()) return;
QPixmap pixmap(24, 24); pixmap.fill(Qt::transparent);
const int size = MemberListModel::kAvatarSize;
QPixmap pixmap(size, size); pixmap.fill(Qt::transparent);
QPainter painter(&pixmap); painter.setRenderHint(QPainter::Antialiasing);
QPainterPath clip; clip.addEllipse(QRectF(0, 0, 24, 24)); painter.setClipPath(clip);
painter.drawImage(QRect(0, 0, 24, 24), image); painter.setClipping(false);
painter.setRenderHint(QPainter::SmoothPixmapTransform);
QPainterPath clip; clip.addEllipse(QRectF(0, 0, size, size)); painter.setClipPath(clip);
painter.drawImage(QRect(0, 0, size, size), image); painter.setClipping(false);
painter.setPen(QPen(Qt::white, 1)); painter.setBrush(item.online ? QColor("#4CAF50") : QColor("#9E9E9E"));
painter.drawEllipse(QRect(17, 17, 6, 6)); painter.end(); item.avatar = pixmap;
painter.drawEllipse(QRect(size - 7, size - 7, 6, 6)); painter.end(); item.avatar = pixmap;
}
MemberListModel::MemberListModel(QObject* parent)
@@ -136,16 +138,17 @@ static void deserialize_member(const uint8_t* src, MemberListItem& item) {
item.name = QString::fromUtf8(name);
QColor c = item.online ? QColor("#4CAF50") : QColor("#9E9E9E");
QPixmap pm(24, 24); pm.fill(Qt::transparent);
const int size = MemberListModel::kAvatarSize;
QPixmap pm(size, size); pm.fill(Qt::transparent);
QPainter p(&pm);
p.setRenderHint(QPainter::Antialiasing);
p.setBrush(c);
p.setPen(Qt::NoPen);
p.drawEllipse(2, 2, 20, 20);
p.drawEllipse(0, 0, size, size);
p.setPen(Qt::white);
QFont f; f.setBold(true); f.setPixelSize(12);
QFont f; f.setBold(true); f.setPixelSize(size / 2);
p.setFont(f);
p.drawText(QRect(0, 0, 24, 24), Qt::AlignCenter, item.name.left(1));
p.drawText(QRect(0, 0, size, size), Qt::AlignCenter, item.name.left(1));
p.end();
item.avatar = pm;
}
+4
View File
@@ -27,6 +27,10 @@ struct MemberListItem {
class MemberListModel : public QAbstractListModel {
Q_OBJECT
public:
/* Высота строки 36 px, между аватарками остаётся 2 px. */
static constexpr int kRowHeight = 36;
static constexpr int kAvatarSize = kRowHeight - 2;
explicit MemberListModel(QObject* parent = nullptr);
int rowCount(const QModelIndex& parent = QModelIndex()) const override;
+9 -6
View File
@@ -83,7 +83,9 @@ QString MessageDelegate::linkAt(const QStyleOptionViewItem& option, const QModel
}
MessageDelegate::MessageDelegate(QObject *parent)
: QStyledItemDelegate(parent) {}
: QStyledItemDelegate(parent) {
GUI_DEBUG("MessageDelegate: avatar size=%dpx", kAvatar);
}
struct VoicePlayState {
uint64_t playbackId = 0;
@@ -442,7 +444,7 @@ MessageDelegate::Layout MessageDelegate::calcLayout(
}
if (!L.narrow) {
int avatarY = L.bubbleRect.bottom() - kAvatar;
int avatarY = qMax(0, L.bubbleRect.bottom() + 1 - kAvatar);
if (!L.isOutgoing)
L.avatarRect = QRect(kMarginH, avatarY, kAvatar, kAvatar);
else
@@ -484,7 +486,7 @@ MessageDelegate::Layout MessageDelegate::calcLayout(
L.videoDurBadgeRect = QRect(bx + thW - 66, thH - 26, 58, 18);
if (!L.narrow) {
int avatarY = L.bubbleRect.bottom() - kAvatar;
int avatarY = qMax(0, L.bubbleRect.bottom() + 1 - kAvatar);
if (!L.isOutgoing)
L.avatarRect = QRect(kMarginH, avatarY, kAvatar, kAvatar);
else
@@ -519,7 +521,7 @@ MessageDelegate::Layout MessageDelegate::calcLayout(
L.imageBadgeRect = QRect(bx + thW - 150, thH - 26, 142, 18);
if (!L.narrow) {
int avatarY = L.bubbleRect.bottom() - kAvatar;
int avatarY = qMax(0, L.bubbleRect.bottom() + 1 - kAvatar);
if (!L.isOutgoing)
L.avatarRect = QRect(kMarginH, avatarY, kAvatar, kAvatar);
else
@@ -557,7 +559,7 @@ MessageDelegate::Layout MessageDelegate::calcLayout(
L.statusRect = QRect(bx + kPadH + ih + 8 - 48, kPadTop + th + 2, L.bubbleWidth - 2*kPadH - ih - 8 + 48 - 40, th);
if (!L.narrow) {
int avatarY = L.bubbleRect.bottom() - kAvatar;
int avatarY = qMax(0, L.bubbleRect.bottom() + 1 - kAvatar);
if (!L.isOutgoing)
L.avatarRect = QRect(kMarginH, avatarY, kAvatar, kAvatar);
else
@@ -687,7 +689,7 @@ MessageDelegate::Layout MessageDelegate::calcLayout(
L.statusRect = QRect(txRect, contentTop + textH + 2, textW, kStatusH);
if (!L.narrow) {
int avatarY = L.bubbleRect.bottom() - kAvatar;
int avatarY = qMax(0, L.bubbleRect.bottom() + 1 - kAvatar);
if (!L.isOutgoing)
L.avatarRect = QRect(kMarginH, avatarY, kAvatar, kAvatar);
else
@@ -1617,6 +1619,7 @@ void MessageDelegate::drawAvatar(QPainter *p, const Layout &L,
p->setRenderHint(QPainter::Antialiasing);
QPainterPath clip;
clip.addEllipse(L.avatarRect);
p->setRenderHint(QPainter::SmoothPixmapTransform);
p->setClipPath(clip);
p->drawPixmap(L.avatarRect, av);
p->restore();
+2 -1
View File
@@ -52,6 +52,8 @@ enum MessageDataRole {
class MessageDelegate : public QStyledItemDelegate {
Q_OBJECT
public:
static constexpr int kAvatar = 54;
explicit MessageDelegate(QObject *parent = nullptr);
void paint(QPainter *painter, const QStyleOptionViewItem &option,
@@ -128,7 +130,6 @@ private:
void drawAvatar(QPainter *p, const Layout &L,
const QModelIndex &index) const;
static constexpr int kAvatar = 36;
static constexpr int kGap = 8;
static constexpr int kRadius = 10;
static constexpr int kPadH = 12;
+1 -1
View File
@@ -77,7 +77,7 @@ static QIcon makeRadioIcon(const QColor& color) {
return icon;
}
static QPixmap makeAvatar(const QColor &color, const QString &letter, int size = 36) {
static QPixmap makeAvatar(const QColor &color, const QString &letter, int size = MessageDelegate::kAvatar) {
QPixmap pix(size, size);
pix.fill(Qt::transparent);
QPainter p(&pix);