avatar painting is returned to delegate; sender names now are not painted in every message

This commit is contained in:
Blue 2022-01-07 17:02:49 +03:00
parent 7130e674c4
commit 9ac0ca10f3
Signed by: blue
GPG Key ID: 9B203B252A63EE38
4 changed files with 93 additions and 73 deletions

View File

@ -338,20 +338,6 @@ void FeedView::paintEvent(QPaintEvent* event)
drawDateDevider(option.rect.bottom(), lastDate, painter); drawDateDevider(option.rect.bottom(), lastDate, painter);
} }
lastDate = currentDate; lastDate = currentDate;
if ((option.rect.y() < 1) || (index.row() == m->rowCount() - 1)) {
drawAvatar(index, option, painter);
} else {
QString mySender = index.data(Models::MessageFeed::Sender).toString();
QModelIndex prevIndex = m->index(index.row() + 1, 0, rootIndex());
if (
(prevIndex.data(Models::MessageFeed::Sender).toString() != mySender) ||
(prevIndex.data(Models::MessageFeed::Date).toDateTime().daysTo(currentDate) != 0)
) {
drawAvatar(index, option, painter);
}
}
} }
if (!lastDate.isNull() && inZone) { //if after drawing all messages there is still space if (!lastDate.isNull() && inZone) { //if after drawing all messages there is still space
drawDateDevider(option.rect.bottom(), lastDate, painter); drawDateDevider(option.rect.bottom(), lastDate, painter);
@ -374,40 +360,6 @@ void FeedView::drawDateDevider(int top, const QDateTime& date, QPainter& painter
painter.restore(); painter.restore();
} }
void FeedView::drawAvatar(const QModelIndex& index, const QStyleOptionViewItem& option, QPainter& painter)
{
int currentRow = index.row();
int y = option.rect.y();
bool firstAttempt = true;
QString mySender = index.data(Models::MessageFeed::Sender).toString();
QDateTime currentDate = index.data(Models::MessageFeed::Date).toDateTime();
QIcon icon(index.data(Models::MessageFeed::Avatar).toString());
while (y < 0 && currentRow > 0) {
QRect rect;
if (firstAttempt) {
firstAttempt = false;
rect = option.rect;
} else {
QModelIndex ci = model()->index(currentRow, 0, rootIndex());
if (
(ci.data(Models::MessageFeed::Sender).toString() != mySender) ||
(ci.data(Models::MessageFeed::Date).toDateTime().daysTo(currentDate) != 0)
) {
break;
}
rect = visualRect(ci);
}
y = std::min(0, rect.bottom() - margin - avatarHeight);
--currentRow;
}
if (index.data(Models::MessageFeed::SentByMe).toBool()) {
painter.drawPixmap(option.rect.width() - avatarHeight - margin, y + halfMargin, icon.pixmap(avatarHeight, avatarHeight));
} else {
painter.drawPixmap(margin, y + halfMargin, icon.pixmap(avatarHeight, avatarHeight));
}
}
void FeedView::verticalScrollbarValueChanged(int value) void FeedView::verticalScrollbarValueChanged(int value)
{ {
vo = verticalScrollBar()->maximum() - value; vo = verticalScrollBar()->maximum() - value;

View File

@ -74,7 +74,6 @@ private:
bool tryToCalculateGeometriesWithNoScrollbars(const QStyleOptionViewItem& option, const QAbstractItemModel* model, uint32_t totalHeight); bool tryToCalculateGeometriesWithNoScrollbars(const QStyleOptionViewItem& option, const QAbstractItemModel* model, uint32_t totalHeight);
void positionProgress(); void positionProgress();
void drawDateDevider(int top, const QDateTime& date, QPainter& painter); void drawDateDevider(int top, const QDateTime& date, QPainter& painter);
void drawAvatar(const QModelIndex& index, const QStyleOptionViewItem& option, QPainter& painter);
private: private:
struct Hint { struct Hint {

View File

@ -20,6 +20,7 @@
#include <QPainter> #include <QPainter>
#include <QApplication> #include <QApplication>
#include <QMouseEvent> #include <QMouseEvent>
#include <QAbstractItemView>
#include "messagedelegate.h" #include "messagedelegate.h"
#include "messagefeed.h" #include "messagefeed.h"
@ -104,7 +105,10 @@ void MessageDelegate::paint(QPainter* painter, const QStyleOptionViewItem& optio
painter->fillRect(option.rect, option.palette.brush(QPalette::Inactive, QPalette::Highlight)); painter->fillRect(option.rect, option.palette.brush(QPalette::Inactive, QPalette::Highlight));
} }
bool ntds = needToDrawSender(index, data);
if (ntds || option.rect.y() < 1) {
paintAvatar(data, index, option, painter);
}
QStyleOptionViewItem opt = option; QStyleOptionViewItem opt = option;
QRect messageRect = option.rect.adjusted(margin, margin / 2, -(avatarHeight + 2 * margin), -margin / 2); QRect messageRect = option.rect.adjusted(margin, margin / 2, -(avatarHeight + 2 * margin), -margin / 2);
@ -122,14 +126,20 @@ void MessageDelegate::paint(QPainter* painter, const QStyleOptionViewItem& optio
messageSize = bodyMetrics.boundingRect(messageRect, Qt::TextWordWrap, data.text).size(); messageSize = bodyMetrics.boundingRect(messageRect, Qt::TextWordWrap, data.text).size();
bodySize = messageSize; bodySize = messageSize;
} }
if (ntds) {
messageSize.rheight() += nickMetrics.lineSpacing(); messageSize.rheight() += nickMetrics.lineSpacing();
}
messageSize.rheight() += dateMetrics.height(); messageSize.rheight() += dateMetrics.height();
QString dateString = data.date.toLocalTime().toString("hh:mm"); QString dateString = data.date.toLocalTime().toString("hh:mm");
if (messageSize.width() < opt.rect.width()) { if (messageSize.width() < opt.rect.width()) {
if (ntds) {
QSize senderSize = nickMetrics.boundingRect(messageRect, 0, data.sender).size(); QSize senderSize = nickMetrics.boundingRect(messageRect, 0, data.sender).size();
if (senderSize.width() > messageSize.width()) { if (senderSize.width() > messageSize.width()) {
messageSize.setWidth(senderSize.width()); messageSize.setWidth(senderSize.width());
} }
}
QSize dateSize = dateMetrics.boundingRect(messageRect, 0, dateString).size(); QSize dateSize = dateMetrics.boundingRect(messageRect, 0, dateString).size();
int addition = 0; int addition = 0;
@ -147,9 +157,11 @@ void MessageDelegate::paint(QPainter* painter, const QStyleOptionViewItem& optio
} }
QRect rect; QRect rect;
if (ntds) {
painter->setFont(nickFont); painter->setFont(nickFont);
painter->drawText(opt.rect, opt.displayAlignment, data.sender, &rect); painter->drawText(opt.rect, opt.displayAlignment, data.sender, &rect);
opt.rect.adjust(0, rect.height() + textMargin, 0, 0); opt.rect.adjust(0, rect.height() + textMargin, 0, 0);
}
painter->save(); painter->save();
switch (data.attach.state) { switch (data.attach.state) {
case Models::none: case Models::none:
@ -244,25 +256,75 @@ void MessageDelegate::paint(QPainter* painter, const QStyleOptionViewItem& optio
} }
} }
void MessageDelegate::paintAvatar(const Models::FeedItem& data, const QModelIndex& index, const QStyleOptionViewItem& option, QPainter* painter) const
{
int currentRow = index.row();
int y = option.rect.y();
bool firstAttempt = true;
QIcon icon(data.avatar);
while (y < 0 && currentRow > 0) {
QRect rect;
if (firstAttempt) {
firstAttempt = false;
rect = option.rect;
} else {
QModelIndex ci = index.siblingAtRow(currentRow);
if (
(ci.data(Models::MessageFeed::Sender).toString() != data.sender) ||
(ci.data(Models::MessageFeed::Date).toDateTime().daysTo(data.date) != 0)
) {
break;
}
//TODO this is really bad, but for now I have no idea how else can I access the view;
const QAbstractItemView* view = static_cast<const QAbstractItemView*>(option.styleObject);
rect = view->visualRect(ci);
}
y = std::min(0, rect.bottom() - margin - avatarHeight);
--currentRow;
}
if (data.sentByMe) {
painter->drawPixmap(option.rect.width() - avatarHeight - margin, y + margin / 2, icon.pixmap(avatarHeight, avatarHeight));
} else {
painter->drawPixmap(margin, y + margin / 2, icon.pixmap(avatarHeight, avatarHeight));
}
}
bool MessageDelegate::needToDrawAvatar(const QModelIndex& index, const Models::FeedItem& data, const QStyleOptionViewItem& option) const
{
return (option.rect.y() < 1) || needToDrawSender(index, data);
}
bool MessageDelegate::needToDrawSender(const QModelIndex& index, const Models::FeedItem& data) const
{
if (index.row() == index.model()->rowCount() - 1) {
return true;
} else {
QModelIndex prevIndex = index.siblingAtRow(index.row() + 1);
return (prevIndex.data(Models::MessageFeed::Sender).toString() != data.sender) ||
(prevIndex.data(Models::MessageFeed::Date).toDateTime().daysTo(data.date) != 0);
}
}
QSize MessageDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const QSize MessageDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const
{ {
QRect messageRect = option.rect.adjusted(0, margin / 2, -(avatarHeight + 3 * margin), -margin / 2); QRect messageRect = option.rect.adjusted(0, margin / 2, -(avatarHeight + 3 * margin), -margin / 2);
QStyleOptionViewItem opt = option; QStyleOptionViewItem opt = option;
opt.rect = messageRect; opt.rect = messageRect;
QVariant va = index.data(Models::MessageFeed::Attach); QVariant vi = index.data(Models::MessageFeed::Bulk);
Models::Attachment attach = qvariant_cast<Models::Attachment>(va); Models::FeedItem data = qvariant_cast<Models::FeedItem>(vi);
QString body = index.data(Models::MessageFeed::Text).toString();
QSize messageSize(0, 0); QSize messageSize(0, 0);
if (body.size() > 0) { if (data.text.size() > 0) {
messageSize = bodyMetrics.boundingRect(messageRect, Qt::TextWordWrap, body).size(); messageSize = bodyMetrics.boundingRect(messageRect, Qt::TextWordWrap, data.text).size();
messageSize.rheight() += textMargin; messageSize.rheight() += textMargin;
} }
switch (attach.state) { switch (data.attach.state) {
case Models::none: case Models::none:
break; break;
case Models::uploading: case Models::uploading:
messageSize.rheight() += Preview::calculateAttachSize(attach.localPath, messageRect).height() + textMargin; messageSize.rheight() += Preview::calculateAttachSize(data.attach.localPath, messageRect).height() + textMargin;
[[fallthrough]]; [[fallthrough]];
case Models::downloading: case Models::downloading:
messageSize.rheight() += barHeight + textMargin; messageSize.rheight() += barHeight + textMargin;
@ -272,25 +334,28 @@ QSize MessageDelegate::sizeHint(const QStyleOptionViewItem& option, const QModel
break; break;
case Models::ready: case Models::ready:
case Models::local: case Models::local:
messageSize.rheight() += Preview::calculateAttachSize(attach.localPath, messageRect).height() + textMargin; messageSize.rheight() += Preview::calculateAttachSize(data.attach.localPath, messageRect).height() + textMargin;
break; break;
case Models::errorDownload: case Models::errorDownload:
messageSize.rheight() += buttonHeight + textMargin; messageSize.rheight() += buttonHeight + textMargin;
messageSize.rheight() += dateMetrics.boundingRect(messageRect, Qt::TextWordWrap, attach.error).size().height() + textMargin; messageSize.rheight() += dateMetrics.boundingRect(messageRect, Qt::TextWordWrap, data.attach.error).size().height() + textMargin;
break; break;
case Models::errorUpload: case Models::errorUpload:
messageSize.rheight() += Preview::calculateAttachSize(attach.localPath, messageRect).height() + textMargin; messageSize.rheight() += Preview::calculateAttachSize(data.attach.localPath, messageRect).height() + textMargin;
messageSize.rheight() += dateMetrics.boundingRect(messageRect, Qt::TextWordWrap, attach.error).size().height() + textMargin; messageSize.rheight() += dateMetrics.boundingRect(messageRect, Qt::TextWordWrap, data.attach.error).size().height() + textMargin;
break; break;
} }
if (needToDrawSender(index, data)) {
messageSize.rheight() += nickMetrics.lineSpacing(); messageSize.rheight() += nickMetrics.lineSpacing();
messageSize.rheight() += textMargin; messageSize.rheight() += textMargin;
}
messageSize.rheight() += dateMetrics.height() > statusIconSize ? dateMetrics.height() : statusIconSize; messageSize.rheight() += dateMetrics.height() > statusIconSize ? dateMetrics.height() : statusIconSize;
if (messageSize.height() < avatarHeight) { // if (messageSize.height() < avatarHeight) {
messageSize.setHeight(avatarHeight); // messageSize.setHeight(avatarHeight);
} // }
messageSize.rheight() += margin; messageSize.rheight() += margin;

View File

@ -65,6 +65,7 @@ protected:
void paintBar(QProgressBar* bar, QPainter* painter, bool sentByMe, QStyleOptionViewItem& option) const; void paintBar(QProgressBar* bar, QPainter* painter, bool sentByMe, QStyleOptionViewItem& option) const;
void paintPreview(const Models::FeedItem& data, QPainter* painter, QStyleOptionViewItem& option) const; void paintPreview(const Models::FeedItem& data, QPainter* painter, QStyleOptionViewItem& option) const;
void paintComment(const Models::FeedItem& data, QPainter* painter, QStyleOptionViewItem& option) const; void paintComment(const Models::FeedItem& data, QPainter* painter, QStyleOptionViewItem& option) const;
void paintAvatar(const Models::FeedItem& data, const QModelIndex& index, const QStyleOptionViewItem& option, QPainter* painter) const;
QPushButton* getButton(const Models::FeedItem& data) const; QPushButton* getButton(const Models::FeedItem& data) const;
QProgressBar* getBar(const Models::FeedItem& data) const; QProgressBar* getBar(const Models::FeedItem& data) const;
QLabel* getStatusIcon(const Models::FeedItem& data) const; QLabel* getStatusIcon(const Models::FeedItem& data) const;
@ -72,6 +73,9 @@ protected:
QLabel* getBody(const Models::FeedItem& data) const; QLabel* getBody(const Models::FeedItem& data) const;
void clearHelperWidget(const Models::FeedItem& data) const; void clearHelperWidget(const Models::FeedItem& data) const;
bool needToDrawAvatar(const QModelIndex& index, const Models::FeedItem& data, const QStyleOptionViewItem& option) const;
bool needToDrawSender(const QModelIndex& index, const Models::FeedItem& data) const;
protected slots: protected slots:
void onButtonPushed() const; void onButtonPushed() const;