File indexing completed on 2024-06-09 04:59:24
0001 /* 0002 SPDX-FileCopyrightText: 2020-2024 Laurent Montel <montel@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "messagedelegatehelperconferencevideo.h" 0008 #include "common/delegatepaintutil.h" 0009 #include "conferencecalldialog/conferenceinfodialog.h" 0010 #include "config-ruqola.h" 0011 #include "misc/avatarcachemanager.h" 0012 #include "rocketchataccount.h" 0013 0014 #include <KLocalizedString> 0015 0016 #include <QAbstractItemView> 0017 #include <QAbstractTextDocumentLayout> 0018 #include <QListView> 0019 #include <QMouseEvent> 0020 #include <QPainter> 0021 #include <QStyleOptionViewItem> 0022 #include <QToolTip> 0023 0024 MessageDelegateHelperConferenceVideo::MessageDelegateHelperConferenceVideo(RocketChatAccount *account, QListView *view, TextSelectionImpl *textSelectionImpl) 0025 : MessageBlockDelegateHelperBase(account, view, textSelectionImpl) 0026 , mInfoIcon(QIcon::fromTheme(QStringLiteral("documentinfo"))) 0027 , mAvatarCacheManager(new AvatarCacheManager(Utils::AvatarType::User, this)) 0028 { 0029 } 0030 0031 MessageDelegateHelperConferenceVideo::~MessageDelegateHelperConferenceVideo() = default; 0032 0033 // Title [margin] <icon info> 0034 // Button join [margin] <list avatar user> 0035 // 0036 void MessageDelegateHelperConferenceVideo::draw(const Block &block, 0037 QPainter *painter, 0038 QRect blockRect, 0039 const QModelIndex &index, 0040 const QStyleOptionViewItem &option) const 0041 { 0042 Q_UNUSED(index) 0043 const ConferenceCallLayout layout = layoutConferenceCall(block, option, blockRect.width()); 0044 // Draw title and buttons 0045 const int positionY = blockRect.y() + option.fontMetrics.ascent(); 0046 painter->drawText(blockRect.x(), positionY, layout.title); 0047 mInfoIcon.paint(painter, layout.infoButtonRect.translated(blockRect.topLeft())); 0048 0049 if (layout.canJoin) { 0050 // Draw join button 0051 const QPen origPen = painter->pen(); 0052 const QBrush origBrush = painter->brush(); 0053 const QPen buttonPen(option.palette.color(QPalette::Highlight).darker()); 0054 QColor backgroundColor = option.palette.color(QPalette::Highlight); 0055 backgroundColor.setAlpha(60); 0056 const QBrush buttonBrush(backgroundColor); 0057 const QRectF joinButtonRect = layout.joinButtonRect.translated(blockRect.topLeft()); 0058 // Rounded rect 0059 painter->setPen(buttonPen); 0060 painter->setBrush(buttonBrush); 0061 painter->drawRoundedRect(joinButtonRect, 5, 5); 0062 painter->setBrush(origBrush); 0063 painter->setPen(origPen); 0064 const QRectF r = joinButtonRect.adjusted((joinButtonRect.width() - layout.joinButtonTextSize.width()) / 2, 0, 0, 0); 0065 painter->drawText(r, i18n("Join")); 0066 } 0067 0068 // Draw avatars! 0069 for (const UserLayout &userLayout : layout.usersLayout) { 0070 const QRectF avatarRect = userLayout.userAvatarRect.translated(blockRect.topLeft()); 0071 #if USE_ROUNDED_RECT_PIXMAP 0072 DelegatePaintUtil::createClipRoundedRectangle(painter, 0073 QRectF(avatarRect.topLeft(), avatarRect.toRect().size()), 0074 avatarRect.topLeft(), 0075 userLayout.avatarPixmap); 0076 #else 0077 painter->drawPixmap(avatarRect.toRect(), userLayout.avatarPixmap); 0078 #endif 0079 } 0080 } 0081 0082 QSize MessageDelegateHelperConferenceVideo::sizeHint(const Block &block, const QModelIndex &index, int maxWidth, const QStyleOptionViewItem &option) const 0083 { 0084 Q_UNUSED(index) 0085 const ConferenceCallLayout layout = layoutConferenceCall(block, option, maxWidth); 0086 int height = layout.titleSize.height() + DelegatePaintUtil::margin(); 0087 // Button 0088 if (layout.canJoin) { 0089 height += layout.joinButtonRect.height(); 0090 } else if (!layout.usersLayout.isEmpty()) { 0091 height += 10 + DelegatePaintUtil::margin(); // TODO customize it 0092 } 0093 return {qMax(0, layout.titleSize.width()), height}; 0094 } 0095 0096 QPoint MessageDelegateHelperConferenceVideo::adaptMousePosition(const QPoint &pos, const Block &block, QRect blocksRect, const QStyleOptionViewItem &option) 0097 { 0098 const ConferenceCallLayout layout = layoutConferenceCall(block, option, blocksRect.width()); 0099 const QPoint relativePos = pos - blocksRect.topLeft() - QPoint(0, layout.titleSize.height() + DelegatePaintUtil::margin()); 0100 return relativePos; 0101 } 0102 0103 bool MessageDelegateHelperConferenceVideo::handleMouseEvent(const Block &block, 0104 QMouseEvent *mouseEvent, 0105 QRect blocksRect, 0106 const QStyleOptionViewItem &option, 0107 const QModelIndex &index) 0108 { 0109 Q_UNUSED(index); 0110 const QEvent::Type eventType = mouseEvent->type(); 0111 switch (eventType) { 0112 case QEvent::MouseButtonRelease: { 0113 const QPoint pos = mouseEvent->pos(); 0114 0115 const ConferenceCallLayout layout = layoutConferenceCall(block, option, blocksRect.width()); 0116 if (layout.infoButtonRect.translated(blocksRect.topLeft()).contains(pos)) { 0117 auto parentWidget = const_cast<QWidget *>(option.widget); 0118 ConferenceInfoDialog dlg(mRocketChatAccount, parentWidget); 0119 dlg.setConferenceId(block.callId()); 0120 dlg.initializeInfo(); 0121 dlg.exec(); 0122 return true; 0123 } 0124 if (layout.canJoin) { 0125 if (layout.joinButtonRect.translated(blocksRect.topLeft()).contains(pos)) { 0126 if (!block.videoConferenceInfo().url().isEmpty()) { 0127 Q_EMIT mRocketChatAccount->openLinkRequested(block.videoConferenceInfo().url()); 0128 return true; 0129 } 0130 return true; 0131 } 0132 } 0133 break; 0134 } 0135 default: 0136 break; 0137 } 0138 0139 return false; 0140 } 0141 0142 bool MessageDelegateHelperConferenceVideo::handleHelpEvent(QHelpEvent *helpEvent, QRect blockRect, const Block &block, const QStyleOptionViewItem &option) 0143 { 0144 const ConferenceCallLayout layout = layoutConferenceCall(block, option, blockRect.width()); 0145 for (const UserLayout &userLayout : layout.usersLayout) { 0146 if (userLayout.userAvatarRect.translated(blockRect.topLeft()).contains(helpEvent->pos())) { 0147 QToolTip::showText(helpEvent->globalPos(), userLayout.userName, mListView); 0148 return true; 0149 } 0150 } 0151 return false; 0152 } 0153 0154 MessageDelegateHelperConferenceVideo::ConferenceCallLayout 0155 MessageDelegateHelperConferenceVideo::layoutConferenceCall(const Block &block, const QStyleOptionViewItem &option, int blockRectWidth) const 0156 { 0157 Q_UNUSED(blockRectWidth) 0158 ConferenceCallLayout layout; 0159 layout.title = block.title(); 0160 layout.titleSize = option.fontMetrics.size(Qt::TextSingleLine, layout.title); 0161 const int iconSize = option.widget->style()->pixelMetric(QStyle::PM_ButtonIconSize); 0162 layout.infoButtonRect = QRect(layout.titleSize.width() + DelegatePaintUtil::margin(), 0, iconSize, iconSize); 0163 // Join Button 0164 layout.canJoin = block.videoConferenceInfo().canJoin(); 0165 if (layout.canJoin) { 0166 layout.joinButtonTextSize = option.fontMetrics.size(Qt::TextSingleLine, i18n("Join")); 0167 layout.joinButtonRect = 0168 QRect(0, layout.infoButtonRect.height() + DelegatePaintUtil::margin(), layout.joinButtonTextSize.width() * 2, layout.joinButtonTextSize.height()); 0169 } 0170 // Users 0171 qreal x = 0; 0172 const QVector<User> users = block.videoConferenceInfo().users(); 0173 for (const auto &user : users) { 0174 UserLayout userLayout; 0175 userLayout.userName = user.userName(); 0176 userLayout.avatarPixmap = makeAvatarPixmap(userLayout.userName, option.widget, layout.titleSize.height()); 0177 userLayout.userAvatarRect = QRectF((layout.canJoin ? layout.joinButtonTextSize.width() * 2 + DelegatePaintUtil::margin() : 0) + x, 0178 layout.infoButtonRect.height() + DelegatePaintUtil::margin(), 0179 iconSize, 0180 iconSize); 0181 layout.usersLayout.append(std::move(userLayout)); 0182 x += iconSize + DelegatePaintUtil::margin(); 0183 } 0184 return layout; 0185 } 0186 0187 void MessageDelegateHelperConferenceVideo::setRocketChatAccount(RocketChatAccount *newRocketChatAccount) 0188 { 0189 mAvatarCacheManager->setCurrentRocketChatAccount(newRocketChatAccount); 0190 MessageBlockDelegateHelperBase::setRocketChatAccount(newRocketChatAccount); 0191 } 0192 0193 QPixmap MessageDelegateHelperConferenceVideo::makeAvatarPixmap(const QString &identifier, const QWidget *widget, int maxHeight) const 0194 { 0195 Utils::AvatarInfo info; 0196 info.avatarType = Utils::AvatarType::User; 0197 info.identifier = identifier; 0198 return mAvatarCacheManager->makeAvatarPixmap(widget, info, maxHeight); 0199 }