1 /*
2     SPDX-FileCopyrightText: 2017, 2020 Friedrich W. H. Kossebau <kossebau@kde.org>
3 
4     SPDX-License-Identifier: LGPL-2.1-or-later
5 */
6 
7 #include "markdownbrowserextension.hpp"
8 
9 // part
10 #include "markdownpart.hpp"
11 #include "markdownview.hpp"
12 // KF
13 #include <KActionCollection>
14 #include <KLocalizedString>
15 // Qt
16 #include <QMimeDatabase>
17 
18 
MarkdownBrowserExtension(MarkdownPart * part)19 MarkdownBrowserExtension::MarkdownBrowserExtension(MarkdownPart* part)
20     : KParts::BrowserExtension(part)
21     , m_part(part)
22     , m_contextMenuActionCollection(new KActionCollection(this))
23 {
24      Q_EMIT enableAction("copy", m_part->view()->hasSelection());
25 }
26 
copy()27 void MarkdownBrowserExtension::copy()
28 {
29     m_part->copySelection();
30 }
31 
updateCopyAction(bool enabled)32 void MarkdownBrowserExtension::updateCopyAction(bool enabled)
33 {
34     Q_EMIT enableAction("copy", enabled);
35 }
36 
requestOpenUrl(const QUrl & url)37 void MarkdownBrowserExtension::requestOpenUrl(const QUrl& url)
38 {
39     Q_EMIT openUrlRequest(url);
40 }
41 
requestOpenUrlNewWindow(const QUrl & url)42 void MarkdownBrowserExtension::requestOpenUrlNewWindow(const QUrl& url)
43 {
44     Q_EMIT createNewWindow(url);
45 }
46 
requestContextMenu(QPoint globalPos,const QUrl & linkUrl,bool hasSelection)47 void MarkdownBrowserExtension::requestContextMenu(QPoint globalPos,
48                                                   const QUrl& linkUrl,
49                                                   bool hasSelection)
50 {
51     // Compare KWebKitPart's WebView::contextMenuEvent & WebEnginePart's WebEngineView::contextMenuEvent
52     // for the patterns used to fill the menu.
53     // QTextBrowser at of Qt 5.15 provides less data though, so for now this is reduced variant.
54 
55     // Clear the previous collection entries first...
56     m_contextMenuActionCollection->clear();
57 
58     // default menu arguments
59     PopupFlags flags = DefaultPopupItems | ShowBookmark;
60     ActionGroupMap mapAction;
61     QString mimeType;
62     QUrl emitUrl;
63 
64     if (!linkUrl.isValid()) {
65         emitUrl = m_part->url();
66         mimeType = QStringLiteral("text/markdown");
67 
68         if (hasSelection) {
69             flags |= ShowTextSelectionItems;
70 
71             QList<QAction*> selectActions;
72 
73             QAction* action = m_part->copySelectionAction();
74             selectActions.append(action);
75 
76             mapAction.insert(QStringLiteral("editactions"), selectActions);
77         }
78     } else {
79         flags |= IsLink;
80         emitUrl = linkUrl;
81 
82         QMimeDatabase mimeDb;
83         if (linkUrl.isLocalFile())
84             mimeType = mimeDb.mimeTypeForUrl(linkUrl).name();
85         else {
86             const QString fileName = linkUrl.fileName();
87 
88             if (!fileName.isEmpty() && !linkUrl.hasFragment() && !linkUrl.hasQuery()) {
89                 QMimeType mime = mimeDb.mimeTypeForFile(fileName);
90                 if (!mime.isDefault()) {
91                     mimeType = mime.name();
92                 }
93             }
94         }
95 
96         QList<QAction*> linkActions;
97 
98         if (hasSelection) {
99             QAction* action = m_part->copySelectionAction();
100             linkActions.append(action);
101         }
102 
103         if (linkUrl.scheme() == QLatin1String("mailto")) {
104             QAction* action = m_part->createCopyEmailAddressAction(m_contextMenuActionCollection, linkUrl);
105             m_contextMenuActionCollection->addAction(QStringLiteral("copylinklocation"), action);
106             linkActions.append(action);
107         } else {
108             QAction* action = m_part->createCopyLinkUrlAction(m_contextMenuActionCollection, linkUrl);
109             m_contextMenuActionCollection->addAction(QStringLiteral("copylinkurl"), action);
110             linkActions.append(action);
111         }
112 
113         mapAction.insert(QStringLiteral("linkactions"), linkActions);
114     }
115 
116     if (!mapAction.isEmpty()) {
117         KParts::OpenUrlArguments args;
118         args.setMimeType(mimeType);
119 
120         KParts::BrowserArguments bargs;
121         bargs.setForcesNewWindow(false);
122 
123         Q_EMIT popupMenu(globalPos, emitUrl, static_cast<mode_t>(-1), args, bargs, flags, mapAction);
124     }
125 }
126 
xOffset()127 int MarkdownBrowserExtension::xOffset()
128 {
129     return m_part->view()->scrollPositionX();
130 }
131 
yOffset()132 int MarkdownBrowserExtension::yOffset()
133 {
134     return m_part->view()->scrollPositionY();
135 }
136