File indexing completed on 2024-12-22 04:46:04
0001 /* 0002 SPDX-FileCopyrightText: 2022-2024 Laurent Montel <montel@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "messagelistlayoutbase.h" 0008 #include "model/messagesmodel.h" 0009 #include "rocketchataccount.h" 0010 #include "room/delegate/messagelistdelegate.h" 0011 0012 #include "room/delegate/messageattachmentdelegatehelperbase.h" 0013 #include "room/delegate/messageblockdelegatehelperbase.h" 0014 #include "room/delegate/messagedelegatehelperreactions.h" 0015 #include "room/delegate/messagedelegatehelpertext.h" 0016 #include "room/delegate/messagedelegatehelperurlpreview.h" 0017 #include "room/delegate/messagelistdelegate.h" 0018 0019 MessageListLayoutBase::MessageListLayoutBase(MessageListDelegate *delegate) 0020 : mDelegate(delegate) 0021 { 0022 } 0023 0024 MessageListLayoutBase::~MessageListLayoutBase() = default; 0025 0026 RocketChatAccount *MessageListLayoutBase::rocketChatAccount() const 0027 { 0028 return mRocketChatAccount; 0029 } 0030 0031 void MessageListLayoutBase::setRocketChatAccount(RocketChatAccount *newRocketChatAccount) 0032 { 0033 mRocketChatAccount = newRocketChatAccount; 0034 } 0035 0036 bool MessageListLayoutBase::sameSenderAsPreviousMessage(const QModelIndex &index, const Message *message) const 0037 { 0038 if (index.row() < 1) { 0039 return false; 0040 } 0041 0042 const auto previousIndex = index.siblingAtRow(index.row() - 1); 0043 const auto previousMessage = previousIndex.data(MessagesModel::MessagePointer).value<Message *>(); 0044 Q_ASSERT(previousMessage); 0045 0046 const int diffDate = mRocketChatAccount ? mRocketChatAccount->ruqolaServerConfig()->messageGroupingPeriod() * 1000 : 0; 0047 if ((message->userId() == previousMessage->userId()) && (message->threadMessageId() == previousMessage->threadMessageId()) 0048 && (message->timeStamp() <= (previousMessage->timeStamp() + diffDate))) 0049 return true; 0050 return false; 0051 } 0052 0053 QString MessageListLayoutBase::senderText(const Message *message) const 0054 { 0055 if (mRocketChatAccount) { 0056 QString displayName; 0057 if (mRocketChatAccount->useRealName() && !message->name().isEmpty()) { 0058 displayName = message->name(); 0059 } else { 0060 if (!message->alias().isEmpty()) { 0061 displayName = message->alias(); 0062 } else { 0063 displayName = message->username(); 0064 } 0065 } 0066 return QLatin1Char('@') + displayName; 0067 } else { 0068 return QLatin1Char('@') + message->username(); 0069 } 0070 } 0071 0072 void MessageListLayoutBase::generateSenderInfo(Layout &layout, const Message *message, const QStyleOptionViewItem &option, const QModelIndex &index) const 0073 { 0074 layout.senderText = senderText(message); 0075 layout.senderFont = option.font; 0076 layout.senderFont.setBold(true); 0077 layout.sameSenderAsPreviousMessage = sameSenderAsPreviousMessage(index, message); 0078 } 0079 0080 void MessageListLayoutBase::generateAttachmentBlockAndUrlPreviewLayout(MessageListDelegate *delegate, 0081 Layout &layout, 0082 const Message *message, 0083 int attachmentsY, 0084 int textLeft, 0085 int maxWidth, 0086 const QStyleOptionViewItem &option, 0087 const QModelIndex &index) const 0088 { 0089 if (message->attachments().isEmpty() && message->blocks().isEmpty() && message->urls().isEmpty()) { 0090 layout.reactionsY = attachmentsY; 0091 } else { 0092 int topAttachment = attachmentsY; 0093 if (!message->attachments().isEmpty()) { 0094 const auto attachments = message->attachments(); 0095 QSize attachmentsSize; 0096 // TODO add spacing between attachment 0097 for (const MessageAttachment &msgAttach : attachments) { 0098 const MessageAttachmentDelegateHelperBase *helper = delegate->attachmentsHelper(msgAttach); 0099 if (attachmentsSize.isEmpty()) { 0100 attachmentsSize = helper ? helper->sizeHint(msgAttach, index, maxWidth, option) : QSize(0, 0); 0101 layout.attachmentsRectList.append(QRect(layout.senderRect.x(), topAttachment, attachmentsSize.width(), attachmentsSize.height())); 0102 topAttachment += attachmentsSize.height(); 0103 } else { 0104 const QSize attSize = helper ? helper->sizeHint(msgAttach, index, maxWidth, option) : QSize(0, 0); 0105 layout.attachmentsRectList.append(QRect(layout.senderRect.x(), topAttachment, attSize.width(), attSize.height())); 0106 attachmentsSize = QSize(qMax(attachmentsSize.width(), attSize.width()), attSize.height() + attachmentsSize.height()); 0107 topAttachment += attSize.height(); 0108 } 0109 } 0110 layout.attachmentsRect = QRect(textLeft, attachmentsY, attachmentsSize.width(), attachmentsSize.height()); 0111 } 0112 int topBlock = topAttachment; 0113 if (!message->blocks().isEmpty()) { 0114 const auto blocks = message->blocks(); 0115 QSize blocksSize; 0116 for (const Block &block : blocks) { 0117 const MessageBlockDelegateHelperBase *helper = delegate->blocksHelper(block); 0118 if (blocksSize.isEmpty()) { 0119 blocksSize = helper ? helper->sizeHint(block, index, maxWidth, option) : QSize(0, 0); 0120 layout.blocksRectList.append(QRect(layout.senderRect.x(), topBlock, blocksSize.width(), blocksSize.height())); 0121 topBlock += blocksSize.height(); 0122 } else { 0123 const QSize blockSize = helper ? helper->sizeHint(block, index, maxWidth, option) : QSize(0, 0); 0124 layout.blocksRectList.append(QRect(layout.senderRect.x(), topBlock, blockSize.width(), blockSize.height())); 0125 blocksSize = QSize(qMax(blocksSize.width(), blockSize.width()), blockSize.height() + blocksSize.height()); 0126 topBlock += blockSize.height(); 0127 } 0128 } 0129 // qDebug() << " topBlock " << topBlock; 0130 layout.blocksRect = QRect(textLeft, topBlock, blocksSize.width(), blocksSize.height()); 0131 } 0132 if (mRocketChatAccount && mRocketChatAccount->previewEmbed()) { 0133 if (!message->urls().isEmpty()) { 0134 const auto urls = message->urls(); 0135 QSize urlsPreviewSize; 0136 int topUrlPreview = topBlock; 0137 for (const MessageUrl &url : urls) { 0138 if (url.hasPreviewUrl()) { 0139 const MessageDelegateHelperUrlPreview *helperUrlPreview = delegate->helperUrlPreview(); 0140 if (urlsPreviewSize.isEmpty()) { 0141 urlsPreviewSize = helperUrlPreview->sizeHint(url, index, maxWidth, option); 0142 layout.messageUrlsRectList.append(QRect(layout.senderRect.x(), topUrlPreview, urlsPreviewSize.width(), urlsPreviewSize.height())); 0143 topUrlPreview += urlsPreviewSize.height(); 0144 } else { 0145 const QSize urlPreviewSize = helperUrlPreview->sizeHint(url, index, maxWidth, option); 0146 layout.messageUrlsRectList.append(QRect(layout.senderRect.x(), topUrlPreview, urlPreviewSize.width(), urlPreviewSize.height())); 0147 urlsPreviewSize = QSize(qMax(urlsPreviewSize.width(), urlPreviewSize.width()), urlPreviewSize.height() + urlsPreviewSize.height()); 0148 topUrlPreview += urlPreviewSize.height(); 0149 } 0150 } else { 0151 layout.messageUrlsRectList.append(QRect{}); 0152 } 0153 } 0154 // qDebug() << " topUrlPreview " << topUrlPreview; 0155 layout.messageUrlsRect = QRect(textLeft, topUrlPreview, urlsPreviewSize.width(), urlsPreviewSize.height()); 0156 } 0157 } 0158 layout.reactionsY = attachmentsY + layout.attachmentsRect.height() + layout.blocksRect.height() + layout.messageUrlsRect.height(); 0159 } 0160 }