From 9ac0ca10f34046b9774659b772ff97d2b029bc73 Mon Sep 17 00:00:00 2001 From: blue Date: Fri, 7 Jan 2022 17:02:49 +0300 Subject: [PATCH] avatar painting is returned to delegate; sender names now are not painted in every message --- ui/widgets/messageline/feedview.cpp | 48 --------- ui/widgets/messageline/feedview.h | 1 - ui/widgets/messageline/messagedelegate.cpp | 113 ++++++++++++++++----- ui/widgets/messageline/messagedelegate.h | 4 + 4 files changed, 93 insertions(+), 73 deletions(-) diff --git a/ui/widgets/messageline/feedview.cpp b/ui/widgets/messageline/feedview.cpp index 618ecfb..1296324 100644 --- a/ui/widgets/messageline/feedview.cpp +++ b/ui/widgets/messageline/feedview.cpp @@ -338,20 +338,6 @@ void FeedView::paintEvent(QPaintEvent* event) drawDateDevider(option.rect.bottom(), lastDate, painter); } 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 drawDateDevider(option.rect.bottom(), lastDate, painter); @@ -374,40 +360,6 @@ void FeedView::drawDateDevider(int top, const QDateTime& date, QPainter& painter 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) { vo = verticalScrollBar()->maximum() - value; diff --git a/ui/widgets/messageline/feedview.h b/ui/widgets/messageline/feedview.h index e3e57b7..5e08946 100644 --- a/ui/widgets/messageline/feedview.h +++ b/ui/widgets/messageline/feedview.h @@ -74,7 +74,6 @@ private: bool tryToCalculateGeometriesWithNoScrollbars(const QStyleOptionViewItem& option, const QAbstractItemModel* model, uint32_t totalHeight); void positionProgress(); void drawDateDevider(int top, const QDateTime& date, QPainter& painter); - void drawAvatar(const QModelIndex& index, const QStyleOptionViewItem& option, QPainter& painter); private: struct Hint { diff --git a/ui/widgets/messageline/messagedelegate.cpp b/ui/widgets/messageline/messagedelegate.cpp index 0fe1ed0..0cf449a 100644 --- a/ui/widgets/messageline/messagedelegate.cpp +++ b/ui/widgets/messageline/messagedelegate.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include "messagedelegate.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)); } - + bool ntds = needToDrawSender(index, data); + if (ntds || option.rect.y() < 1) { + paintAvatar(data, index, option, painter); + } QStyleOptionViewItem opt = option; QRect messageRect = option.rect.adjusted(margin, margin / 2, -(avatarHeight + 2 * margin), -margin / 2); @@ -122,13 +126,19 @@ void MessageDelegate::paint(QPainter* painter, const QStyleOptionViewItem& optio messageSize = bodyMetrics.boundingRect(messageRect, Qt::TextWordWrap, data.text).size(); bodySize = messageSize; } - messageSize.rheight() += nickMetrics.lineSpacing(); + + if (ntds) { + messageSize.rheight() += nickMetrics.lineSpacing(); + } messageSize.rheight() += dateMetrics.height(); QString dateString = data.date.toLocalTime().toString("hh:mm"); + if (messageSize.width() < opt.rect.width()) { - QSize senderSize = nickMetrics.boundingRect(messageRect, 0, data.sender).size(); - if (senderSize.width() > messageSize.width()) { - messageSize.setWidth(senderSize.width()); + if (ntds) { + QSize senderSize = nickMetrics.boundingRect(messageRect, 0, data.sender).size(); + if (senderSize.width() > messageSize.width()) { + messageSize.setWidth(senderSize.width()); + } } QSize dateSize = dateMetrics.boundingRect(messageRect, 0, dateString).size(); int addition = 0; @@ -147,9 +157,11 @@ void MessageDelegate::paint(QPainter* painter, const QStyleOptionViewItem& optio } QRect rect; - painter->setFont(nickFont); - painter->drawText(opt.rect, opt.displayAlignment, data.sender, &rect); - opt.rect.adjust(0, rect.height() + textMargin, 0, 0); + if (ntds) { + painter->setFont(nickFont); + painter->drawText(opt.rect, opt.displayAlignment, data.sender, &rect); + opt.rect.adjust(0, rect.height() + textMargin, 0, 0); + } painter->save(); switch (data.attach.state) { 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(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 { QRect messageRect = option.rect.adjusted(0, margin / 2, -(avatarHeight + 3 * margin), -margin / 2); QStyleOptionViewItem opt = option; opt.rect = messageRect; - QVariant va = index.data(Models::MessageFeed::Attach); - Models::Attachment attach = qvariant_cast(va); - QString body = index.data(Models::MessageFeed::Text).toString(); + QVariant vi = index.data(Models::MessageFeed::Bulk); + Models::FeedItem data = qvariant_cast(vi); QSize messageSize(0, 0); - if (body.size() > 0) { - messageSize = bodyMetrics.boundingRect(messageRect, Qt::TextWordWrap, body).size(); + if (data.text.size() > 0) { + messageSize = bodyMetrics.boundingRect(messageRect, Qt::TextWordWrap, data.text).size(); messageSize.rheight() += textMargin; } - switch (attach.state) { + switch (data.attach.state) { case Models::none: break; case Models::uploading: - messageSize.rheight() += Preview::calculateAttachSize(attach.localPath, messageRect).height() + textMargin; + messageSize.rheight() += Preview::calculateAttachSize(data.attach.localPath, messageRect).height() + textMargin; [[fallthrough]]; case Models::downloading: messageSize.rheight() += barHeight + textMargin; @@ -272,25 +334,28 @@ QSize MessageDelegate::sizeHint(const QStyleOptionViewItem& option, const QModel break; case Models::ready: case Models::local: - messageSize.rheight() += Preview::calculateAttachSize(attach.localPath, messageRect).height() + textMargin; + messageSize.rheight() += Preview::calculateAttachSize(data.attach.localPath, messageRect).height() + textMargin; break; case Models::errorDownload: 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; case Models::errorUpload: - messageSize.rheight() += Preview::calculateAttachSize(attach.localPath, messageRect).height() + textMargin; - messageSize.rheight() += dateMetrics.boundingRect(messageRect, Qt::TextWordWrap, attach.error).size().height() + textMargin; + messageSize.rheight() += Preview::calculateAttachSize(data.attach.localPath, messageRect).height() + textMargin; + messageSize.rheight() += dateMetrics.boundingRect(messageRect, Qt::TextWordWrap, data.attach.error).size().height() + textMargin; break; } - messageSize.rheight() += nickMetrics.lineSpacing(); - messageSize.rheight() += textMargin; + if (needToDrawSender(index, data)) { + messageSize.rheight() += nickMetrics.lineSpacing(); + messageSize.rheight() += textMargin; + } + messageSize.rheight() += dateMetrics.height() > statusIconSize ? dateMetrics.height() : statusIconSize; - if (messageSize.height() < avatarHeight) { - messageSize.setHeight(avatarHeight); - } +// if (messageSize.height() < avatarHeight) { +// messageSize.setHeight(avatarHeight); +// } messageSize.rheight() += margin; diff --git a/ui/widgets/messageline/messagedelegate.h b/ui/widgets/messageline/messagedelegate.h index 7403285..5792e01 100644 --- a/ui/widgets/messageline/messagedelegate.h +++ b/ui/widgets/messageline/messagedelegate.h @@ -65,12 +65,16 @@ protected: void paintBar(QProgressBar* bar, QPainter* painter, bool sentByMe, 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 paintAvatar(const Models::FeedItem& data, const QModelIndex& index, const QStyleOptionViewItem& option, QPainter* painter) const; QPushButton* getButton(const Models::FeedItem& data) const; QProgressBar* getBar(const Models::FeedItem& data) const; QLabel* getStatusIcon(const Models::FeedItem& data) const; QLabel* getPencilIcon(const Models::FeedItem& data) const; QLabel* getBody(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: void onButtonPushed() const;