0.2.0 finalization

This commit is contained in:
Blue 2022-01-09 17:32:23 +03:00
parent 8a2658e4fc
commit 4d3ba6b11f
Signed by untrusted user: blue
GPG key ID: 9B203B252A63EE38
12 changed files with 194 additions and 179 deletions

View file

@ -26,8 +26,8 @@
#include "messagedelegate.h"
#include "messagefeed.h"
constexpr int avatarHeight = 50;
constexpr int margin = 6;
int MessageDelegate::avatarHeight(50);
int MessageDelegate::margin(6);
constexpr int textMargin = 2;
constexpr int statusIconSize = 16;
constexpr float nickFontMultiplier = 1.1;
@ -45,6 +45,7 @@ MessageDelegate::MessageDelegate(QObject* parent):
nickMetrics(nickFont),
dateMetrics(dateFont),
buttonHeight(0),
buttonWidth(0),
barHeight(0),
buttons(new std::map<QString, FeedButton*>()),
bars(new std::map<QString, QProgressBar*>()),
@ -55,8 +56,9 @@ MessageDelegate::MessageDelegate(QObject* parent):
idsToKeep(new std::set<QString>()),
clearingWidgets(false)
{
QPushButton btn;
QPushButton btn(QCoreApplication::translate("MessageLine", "Download"));
buttonHeight = btn.sizeHint().height();
buttonWidth = btn.sizeHint().width();
QProgressBar bar;
barHeight = bar.sizeHint().height();
@ -107,141 +109,79 @@ void MessageDelegate::paint(QPainter* painter, const QStyleOptionViewItem& optio
painter->save();
painter->setRenderHint(QPainter::Antialiasing, true);
// if (option.state & QStyle::State_MouseOver) {
// painter->fillRect(option.rect, option.palette.brush(QPalette::Inactive, QPalette::Highlight));
// }
paintBubble(data, painter, option);
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);
opt.rect = option.rect.adjusted(bubbleMargin, bubbleMargin, -bubbleMargin, -bubbleMargin / 2);
if (!data.sentByMe) {
opt.displayAlignment = Qt::AlignLeft | Qt::AlignTop;
messageRect.adjust(avatarHeight + margin, 0, avatarHeight + margin, 0);
} else {
opt.displayAlignment = Qt::AlignRight | Qt::AlignTop;
}
QPoint bubbleBegin = messageRect.topLeft();
messageRect.adjust(bubbleMargin, bubbleMargin, -bubbleMargin, -bubbleMargin / 2);
opt.rect = messageRect;
QSize messageSize(0, 0);
QSize bodySize(0, 0);
if (data.text.size() > 0) {
messageSize = bodyMetrics.boundingRect(messageRect, Qt::TextWordWrap, data.text).size();
bodySize = messageSize;
}
messageSize.rheight() += dateMetrics.height();
QString dateString = data.date.toLocalTime().toString("hh:mm");
if (messageSize.width() < opt.rect.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;
if (data.correction.corrected) {
addition += margin + statusIconSize;
}
if (data.sentByMe) {
addition += margin + statusIconSize;
}
if (dateSize.width() + addition > messageSize.width()) {
messageSize.setWidth(dateSize.width() + addition);
}
} else {
messageSize.setWidth(opt.rect.width());
}
painter->save();
int storedY = opt.rect.y();
if (ntds) {
opt.rect.adjust(0, nickMetrics.lineSpacing() + textMargin, 0, 0);
}
int attWidth(0);
switch (data.attach.state) {
case Models::none:
clearHelperWidget(data); //i can't imagine the situation where it's gonna be needed
break; //but it's a possible performance problem
case Models::uploading:
attWidth = std::max(paintPreview(data, painter, opt), attWidth);
[[fallthrough]];
case Models::downloading:
messageSize.setWidth(opt.rect.width());
messageSize.rheight() += barHeight + textMargin + opt.rect.y() - storedY;
paintBubble(data, painter, messageSize, opt, bubbleBegin);
attWidth = std::max(paintBar(getBar(data), painter, data.sentByMe, opt), attWidth);
break;
case Models::remote:
attWidth = std::max(paintButton(getButton(data), painter, data.sentByMe, opt), attWidth);
break;
case Models::ready:
case Models::local:
clearHelperWidget(data);
attWidth = std::max(paintPreview(data, painter, opt), attWidth);
break;
case Models::errorDownload: {
attWidth = std::max(paintButton(getButton(data), painter, data.sentByMe, opt), attWidth);
attWidth = std::max(paintComment(data, painter, opt), attWidth);
}
break;
case Models::errorUpload:{
clearHelperWidget(data);
attWidth = std::max(paintPreview(data, painter, opt), attWidth);
attWidth = std::max(paintComment(data, painter, opt), attWidth);
}
break;
}
painter->restore();
if (data.attach.state != Models::uploading && data.attach.state != Models::downloading) {
messageSize.rheight() += opt.rect.y() - storedY;
messageSize.setWidth(std::max(attWidth, messageSize.width()));
paintBubble(data, painter, messageSize, opt, bubbleBegin);
bodySize = bodyMetrics.boundingRect(opt.rect, Qt::TextWordWrap, data.text).size();
}
QRect rect;
if (ntds) {
painter->setFont(nickFont);
int storedY2 = opt.rect.y();
opt.rect.setY(storedY);
painter->drawText(opt.rect, opt.displayAlignment, data.sender, &rect);
opt.rect.setY(storedY2);
opt.rect.adjust(0, nickMetrics.lineSpacing() + textMargin, 0, 0);
}
painter->save();
switch (data.attach.state) {
case Models::none:
clearHelperWidget(data); //i can't imagine the situation where it's gonna be needed
break; //but it's a possible performance problem
case Models::uploading:
paintPreview(data, painter, opt);
[[fallthrough]];
case Models::downloading:
paintBar(getBar(data), painter, data.sentByMe, opt);
break;
case Models::remote:
paintButton(getButton(data), painter, data.sentByMe, opt);
break;
case Models::ready:
case Models::local:
clearHelperWidget(data);
paintPreview(data, painter, opt);
break;
case Models::errorDownload: {
paintButton(getButton(data), painter, data.sentByMe, opt);
paintComment(data, painter, opt);
}
break;
case Models::errorUpload:{
clearHelperWidget(data);
paintPreview(data, painter, opt);
paintComment(data, painter, opt);
}
break;
}
painter->restore();
int messageLeft = INT16_MAX;
int messageRight = opt.rect.x() + messageSize.width();
QWidget* vp = static_cast<QWidget*>(painter->device());
if (data.text.size() > 0) {
QLabel* body = getBody(data);
body->setParent(vp);
body->setMaximumWidth(bodySize.width());
body->setMinimumWidth(bodySize.width());
body->setMinimumHeight(bodySize.height());
body->setMaximumHeight(bodySize.height());
body->setAlignment(opt.displayAlignment);
messageLeft = opt.rect.x();
if (data.sentByMe) {
messageLeft = opt.rect.topRight().x() - bodySize.width();
}
body->move(messageLeft, opt.rect.y());
body->setMinimumSize(bodySize);
body->setMaximumSize(bodySize);
body->move(opt.rect.left(), opt.rect.y());
body->show();
opt.rect.adjust(0, bodySize.height() + textMargin, 0, 0);
}
painter->setFont(dateFont);
QColor q = painter->pen().color();
QString dateString = data.date.toLocalTime().toString("hh:mm");
q.setAlpha(180);
painter->setPen(q);
painter->drawText(opt.rect, opt.displayAlignment, dateString, &rect);
@ -250,7 +190,7 @@ void MessageDelegate::paint(QPainter* painter, const QStyleOptionViewItem& optio
QLabel* statusIcon = getStatusIcon(data);
statusIcon->setParent(vp);
statusIcon->move(opt.rect.topRight().x() - messageSize.width(), currentY);
statusIcon->move(opt.rect.left(), currentY);
statusIcon->show();
opt.rect.adjust(0, statusIconSize + textMargin, 0, 0);
@ -261,9 +201,9 @@ void MessageDelegate::paint(QPainter* painter, const QStyleOptionViewItem& optio
pencilIcon->setParent(vp);
if (data.sentByMe) {
pencilIcon->move(opt.rect.topRight().x() - messageSize.width() + statusIconSize + margin, currentY);
pencilIcon->move(opt.rect.left() + statusIconSize + margin, currentY);
} else {
pencilIcon->move(messageRight - statusIconSize - margin, currentY);
pencilIcon->move(opt.rect.right() - statusIconSize - margin, currentY);
}
pencilIcon->show();
} else {
@ -281,19 +221,16 @@ void MessageDelegate::paint(QPainter* painter, const QStyleOptionViewItem& optio
}
}
void MessageDelegate::paintBubble(const Models::FeedItem& data, QPainter* painter, const QSize& messageSize, QStyleOptionViewItem& option, QPoint bubbleBegin) const
void MessageDelegate::paintBubble(const Models::FeedItem& data, QPainter* painter, const QStyleOptionViewItem& option) const
{
painter->save();
if (data.sentByMe) {
bubbleBegin.setX(option.rect.topRight().x() - messageSize.width() - bubbleMargin);
painter->setBrush(option.palette.brush(QPalette::Inactive, QPalette::Highlight));
} else {
painter->setBrush(option.palette.brush(QPalette::Window));
}
QSize bubbleAddition(2 * bubbleMargin, 1.5 * bubbleMargin);
QRect bubble(bubbleBegin, messageSize + bubbleAddition);
painter->setPen(Qt::NoPen);
painter->drawRoundedRect(bubble, bubbleBorderRadius, bubbleBorderRadius);
painter->drawRoundedRect(option.rect, bubbleBorderRadius, bubbleBorderRadius);
painter->restore();
}
@ -330,7 +267,7 @@ void MessageDelegate::paintAvatar(const Models::FeedItem& data, const QModelInde
int ax;
if (data.sentByMe) {
ax = option.rect.width() - avatarHeight - margin;
ax = option.rect.x() + option.rect.width() + margin;
} else {
ax = margin;
}
@ -381,36 +318,51 @@ QSize MessageDelegate::sizeHint(const QStyleOptionViewItem& option, const QModel
[[fallthrough]];
case Models::downloading:
messageSize.rheight() += barHeight + textMargin;
messageSize.setWidth(messageRect.width());
break;
case Models::remote:
messageSize.rheight() += buttonHeight + textMargin;
messageSize.setWidth(std::max(messageSize.width(), buttonWidth));
break;
case Models::ready:
case Models::local:
messageSize.rheight() += Preview::calculateAttachSize(data.attach.localPath, messageRect).height() + textMargin;
case Models::local: {
QSize aSize = Preview::calculateAttachSize(data.attach.localPath, messageRect);
messageSize.rheight() += aSize.height() + textMargin;
messageSize.setWidth(std::max(messageSize.width(), aSize.width()));
}
break;
case Models::errorDownload:
messageSize.rheight() += buttonHeight + textMargin;
messageSize.rheight() += dateMetrics.boundingRect(messageRect, Qt::TextWordWrap, data.attach.error).size().height() + textMargin;
case Models::errorDownload: {
QSize commentSize = dateMetrics.boundingRect(messageRect, Qt::TextWordWrap, data.attach.error).size();
messageSize.rheight() += commentSize.height() + buttonHeight + textMargin * 2;
messageSize.setWidth(std::max(messageSize.width(), std::max(commentSize.width(), buttonWidth)));
}
break;
case Models::errorUpload:
messageSize.rheight() += Preview::calculateAttachSize(data.attach.localPath, messageRect).height() + textMargin;
messageSize.rheight() += dateMetrics.boundingRect(messageRect, Qt::TextWordWrap, data.attach.error).size().height() + textMargin;
case Models::errorUpload: {
QSize aSize = Preview::calculateAttachSize(data.attach.localPath, messageRect);
QSize commentSize = dateMetrics.boundingRect(messageRect, Qt::TextWordWrap, data.attach.error).size();
messageSize.rheight() += aSize.height() + commentSize.height() + textMargin * 2;
messageSize.setWidth(std::max(messageSize.width(), std::max(commentSize.width(), aSize.width())));
}
break;
}
if (needToDrawSender(index, data)) {
messageSize.rheight() += nickMetrics.lineSpacing() + textMargin;
QSize senderSize = nickMetrics.boundingRect(messageRect, 0, data.sender).size();
messageSize.rheight() += senderSize.height() + textMargin;
messageSize.setWidth(std::max(senderSize.width(), messageSize.width()));
}
messageSize.rheight() += bubbleMargin + bubbleMargin / 2;
messageSize.rheight() += dateMetrics.height() > statusIconSize ? dateMetrics.height() : statusIconSize;
// if (messageSize.height() < avatarHeight) {
// messageSize.setHeight(avatarHeight);
// }
messageSize.rheight() += margin;
QString dateString = data.date.toLocalTime().toString("hh:mm");
QSize dateSize = dateMetrics.boundingRect(messageRect, 0, dateString).size();
messageSize.rheight() += bubbleMargin * 1.5;
messageSize.rheight() += dateSize.height() > statusIconSize ? dateSize.height() : statusIconSize;
int statusWidth = dateSize.width() + statusIconSize + margin;
if (data.correction.corrected) {
statusWidth += statusIconSize + margin;
}
messageSize.setWidth(std::max(statusWidth, messageSize.width()));
messageSize.rwidth() += 2 * bubbleMargin;
return messageSize;
}
@ -508,7 +460,7 @@ int MessageDelegate::paintPreview(const Models::FeedItem& data, QPainter* painte
preview->actualize(data.attach.localPath, size, option.rect.topLeft());
} else {
QWidget* vp = static_cast<QWidget*>(painter->device());
preview = new Preview(data.attach.localPath, size, option.rect.topLeft(), data.sentByMe, vp);
preview = new Preview(data.attach.localPath, size, option.rect.topLeft(), vp);
previews->insert(std::make_pair(data.id, preview));
}