1 /*
2    SPDX-FileCopyrightText: 2020-2021 Laurent Montel <montel@kde.org>
3 
4    SPDX-License-Identifier: LGPL-2.0-or-later
5 */
6 
7 #include "messageattachmentdelegatehelpervideo.h"
8 #include "common/delegatepaintutil.h"
9 #include "common/delegateutil.h"
10 #include "dialogs/showvideodialog.h"
11 #include "rocketchataccount.h"
12 #include "ruqola.h"
13 #include "ruqolawidgets_debug.h"
14 
15 #include <KLocalizedString>
16 
17 #include <KMessageBox>
18 #include <QAbstractItemView>
19 #include <QMouseEvent>
20 #include <QPainter>
21 #include <QPointer>
22 #include <QStyleOptionViewItem>
23 
MessageAttachmentDelegateHelperVideo()24 MessageAttachmentDelegateHelperVideo::MessageAttachmentDelegateHelperVideo()
25     : mDownloadIcon(QIcon::fromTheme(QStringLiteral("cloud-download")))
26     , mVisibilityIcon(QIcon::fromTheme(QStringLiteral("visibility")))
27 {
28 }
29 
30 MessageAttachmentDelegateHelperVideo::~MessageAttachmentDelegateHelperVideo() = default;
31 
draw(const MessageAttachment & msgAttach,QPainter * painter,QRect messageRect,const QModelIndex & index,const QStyleOptionViewItem & option) const32 void MessageAttachmentDelegateHelperVideo::draw(const MessageAttachment &msgAttach,
33                                                 QPainter *painter,
34                                                 QRect messageRect,
35                                                 const QModelIndex &index,
36                                                 const QStyleOptionViewItem &option) const
37 {
38     Q_UNUSED(index)
39     const VideoLayout layout = layoutVideo(msgAttach, option, messageRect.width());
40     // Draw title and buttons
41     painter->drawText(messageRect.x(), messageRect.y() + option.fontMetrics.ascent(), layout.title);
42 
43     mVisibilityIcon.paint(painter, layout.showButtonRect.translated(messageRect.topLeft()));
44     mDownloadIcon.paint(painter, layout.downloadButtonRect.translated(messageRect.topLeft()));
45 
46     const int nextY = messageRect.y() + layout.titleSize.height() + DelegatePaintUtil::margin();
47 
48     drawDescription(msgAttach, messageRect, painter, nextY);
49 }
50 
sizeHint(const MessageAttachment & msgAttach,const QModelIndex & index,int maxWidth,const QStyleOptionViewItem & option) const51 QSize MessageAttachmentDelegateHelperVideo::sizeHint(const MessageAttachment &msgAttach,
52                                                      const QModelIndex &index,
53                                                      int maxWidth,
54                                                      const QStyleOptionViewItem &option) const
55 {
56     Q_UNUSED(index)
57     const VideoLayout layout = layoutVideo(msgAttach, option, maxWidth);
58     int height = layout.titleSize.height() + DelegatePaintUtil::margin();
59     int descriptionWidth = 0;
60     if (!layout.description.isEmpty()) {
61         descriptionWidth = layout.descriptionSize.width();
62         height += layout.descriptionSize.height() + DelegatePaintUtil::margin();
63     }
64     return {qMax(qMax(0, layout.titleSize.width()), descriptionWidth), height};
65 }
66 
handleMouseEvent(const MessageAttachment & msgAttach,QMouseEvent * mouseEvent,QRect attachmentsRect,const QStyleOptionViewItem & option,const QModelIndex & index)67 bool MessageAttachmentDelegateHelperVideo::handleMouseEvent(const MessageAttachment &msgAttach,
68                                                             QMouseEvent *mouseEvent,
69                                                             QRect attachmentsRect,
70                                                             const QStyleOptionViewItem &option,
71                                                             const QModelIndex &index)
72 {
73     if (mouseEvent->type() == QEvent::MouseButtonRelease) {
74         const QPoint pos = mouseEvent->pos();
75 
76         VideoLayout layout = layoutVideo(msgAttach, option, attachmentsRect.width());
77         if (layout.downloadButtonRect.translated(attachmentsRect.topLeft()).contains(pos)) {
78             auto *parentWidget = const_cast<QWidget *>(option.widget);
79             DelegateUtil::saveFile(parentWidget, layout.videoPath, i18n("Save Image"));
80             return true;
81         } else if (attachmentsRect.contains(pos) || layout.showButtonRect.translated(attachmentsRect.topLeft()).contains(pos)) {
82             auto *parentWidget = const_cast<QWidget *>(option.widget);
83             ShowVideoDialog dlg(parentWidget);
84             dlg.setVideoUrl(QUrl::fromLocalFile(layout.videoPath));
85             dlg.exec();
86             return true;
87         }
88     }
89 
90     return MessageDelegateHelperBase::handleMouseEvent(msgAttach, mouseEvent, attachmentsRect, option, index);
91 }
92 
93 MessageAttachmentDelegateHelperVideo::VideoLayout
layoutVideo(const MessageAttachment & msgAttach,const QStyleOptionViewItem & option,int attachmentsWidth) const94 MessageAttachmentDelegateHelperVideo::layoutVideo(const MessageAttachment &msgAttach, const QStyleOptionViewItem &option, int attachmentsWidth) const
95 {
96     VideoLayout layout;
97     const QUrl url = Ruqola::self()->rocketChatAccount()->attachmentUrlFromLocalCache(msgAttach.link());
98     // or we could do layout.attachment = msgAttach; if we need many fields from it
99     layout.title = msgAttach.title();
100     layout.description = msgAttach.description();
101     layout.titleSize = option.fontMetrics.size(Qt::TextSingleLine, layout.title);
102     layout.descriptionSize = documentDescriptionForIndexSize(msgAttach, attachmentsWidth);
103     const int iconSize = option.widget->style()->pixelMetric(QStyle::PM_ButtonIconSize);
104     layout.showButtonRect = QRect(layout.titleSize.width() + DelegatePaintUtil::margin(), 0, iconSize, iconSize);
105     layout.downloadButtonRect = layout.showButtonRect.translated(iconSize + DelegatePaintUtil::margin(), 0);
106     if (url.isLocalFile()) {
107         layout.videoPath = url.toLocalFile();
108     }
109     return layout;
110 }
111