21#include <QWebEngineContextMenuRequest>
25 , m_isContentEditable(false)
26 , m_isContentSelected(false)
27 , m_mediaPaused(false)
31 QString source =
QL1S(
"(function() {"
32 "var e = document.elementFromPoint(%1, %2);"
35 "function isMediaElement(e) {"
36 " return e.tagName.toLowerCase() == 'audio' || e.tagName.toLowerCase() == 'video';"
38 "function isEditableElement(e) {"
39 " if (e.isContentEditable)"
41 " if (e.tagName.toLowerCase() == 'input' || e.tagName.toLowerCase() == 'textarea')"
42 " return e.getAttribute('readonly') != 'readonly';"
45 "function isSelected(e) {"
46 " var selection = window.getSelection();"
47 " if (selection.type != 'Range')"
49 " return window.getSelection().containsNode(e, true);"
51 "function attributeStr(e, a) {"
52 " return e.getAttribute(a) || '';"
55 " baseUrl: document.baseURI,"
56 " alternateText: e.getAttribute('alt'),"
59 " contentEditable: isEditableElement(e),"
60 " contentSelected: isSelected(e),"
64 " tagName: e.tagName.toLowerCase()"
66 "var r = e.getBoundingClientRect();"
67 "res.boundingRect = [r.top, r.left, r.width, r.height];"
68 "if (e.tagName.toLowerCase() == 'img')"
69 " res.imageUrl = attributeStr(e, 'src').trim();"
70 "if (e.tagName.toLowerCase() == 'a') {"
71 " res.linkTitle = e.text;"
72 " res.linkUrl = attributeStr(e, 'href').trim();"
75 " if (res.linkTitle == '' && e.tagName.toLowerCase() == 'a')"
76 " res.linkTitle = e.text;"
77 " if (res.linkUrl == '' && e.tagName.toLowerCase() == 'a')"
78 " res.linkUrl = attributeStr(e, 'href').trim();"
79 " if (res.mediaUrl == '' && isMediaElement(e)) {"
80 " res.mediaUrl = e.currentSrc;"
81 " res.mediaPaused = e.paused;"
82 " res.mediaMuted = e.muted;"
84 " e = e.parentElement;"
89 auto *p =
const_cast<WebPage*
>(page);
90 m_viewportPos = p->mapToViewport(m_pos);
91 const QString &js = source.arg(m_viewportPos.x()).arg(m_viewportPos.y());
97 if (data.position() != m_pos) {
101 m_linkTitle = data.linkText();
102 m_linkUrl = data.linkUrl();
103 m_isContentEditable = data.isContentEditable();
104 m_isContentSelected = !data.selectedText().isEmpty();
106 switch (data.mediaType()) {
107 case QWebEngineContextMenuRequest::MediaTypeImage:
108 m_imageUrl = data.mediaUrl();
111 case QWebEngineContextMenuRequest::MediaTypeVideo:
112 case QWebEngineContextMenuRequest::MediaTypeAudio:
113 m_mediaUrl = data.mediaUrl();
128 return m_alternateText;
133 return m_boundingRect;
143 return m_isContentEditable;
148 return m_isContentSelected;
173 return m_mediaPaused;
188 return m_viewportPos;
196void WebHitTestResult::init(
const QUrl &url,
const QVariantMap &map)
202 m_baseUrl = map.value(
QSL(
"baseUrl")).toUrl();
203 m_alternateText = map.value(
QSL(
"alternateText")).toString();
204 m_imageUrl = map.value(
QSL(
"imageUrl")).toUrl();
205 m_isContentEditable = map.value(
QSL(
"contentEditable")).toBool();
206 m_isContentSelected = map.value(
QSL(
"contentSelected")).toBool();
207 m_linkTitle = map.value(
QSL(
"linkTitle")).toString();
208 m_linkUrl = map.value(
QSL(
"linkUrl")).toUrl();
209 m_mediaUrl = map.value(
QSL(
"mediaUrl")).toUrl();
210 m_mediaPaused = map.value(
QSL(
"mediaPaused")).toBool();
211 m_mediaMuted = map.value(
QSL(
"mediaMuted")).toBool();
212 m_tagName = map.value(
QSL(
"tagName")).toString();
214 const QVariantList &rect = map.value(
QSL(
"boundingRect")).toList();
215 if (rect.size() == 4)
216 m_boundingRect = QRect(rect.at(0).toInt(), rect.at(1).toInt(), rect.at(2).toInt(), rect.at(3).toInt());
218 if (!m_imageUrl.isEmpty())
219 m_imageUrl = url.resolved(m_imageUrl);
220 if (!m_linkUrl.isEmpty())
221 m_linkUrl = m_baseUrl.resolved(m_linkUrl);
222 if (!m_mediaUrl.isEmpty())
223 m_mediaUrl = url.resolved(m_mediaUrl);
QPointF viewportPos() const
QRect boundingRect() const
QString linkTitle() const
bool isContentSelected() const
WebHitTestResult(const WebPage *page, const QPoint &pos)
void updateWithContextMenuData(const QWebEngineContextMenuRequest &data)
QString alternateText() const
bool isContentEditable() const